```{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, DataKinds, PolyKinds,

#endif

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Singletons.Tuple
-- Copyright   :  (C) 2013 Richard Eisenberg
-- Maintainer  :  Richard Eisenberg (eir@cis.upenn.edu)
-- Stability   :  experimental
-- Portability :  non-portable
--
-- Defines functions and datatypes relating to the singleton for tuples,
-- including a singletons version of all the definitions in @Data.Tuple@.
--
-- Because many of these definitions are produced by Template Haskell,
-- it is not possible to create proper Haddock documentation. Please look
-- up the corresponding operation in @Data.Tuple@. Also, please excuse
-- the apparent repeated variable names. This is due to an interaction
--
----------------------------------------------------------------------------

module Data.Singletons.Tuple (
-- * Singleton definitions
Sing(STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7),
STuple0, STuple2, STuple3, STuple4, STuple5, STuple6, STuple7,

-- * Singletons from @Data.Tuple@
Fst, sFst, Snd, sSnd, Curry, sCurry, Uncurry, sUncurry, Swap, sSwap
) where

import Data.Singletons.Instances
import Data.Singletons.TH

\$(singletonsOnly [d|
-- | Extract the first component of a pair.
fst                     :: (a,b) -> a
fst (x,_)               =  x

-- | Extract the second component of a pair.
snd                     :: (a,b) -> b
snd (_,y)               =  y

-- | 'curry' converts an uncurried function to a curried function.
curry                   :: ((a, b) -> c) -> a -> b -> c
curry f x y             =  f (x, y)

-- | 'uncurry' converts a curried function to a function on pairs.
uncurry                 :: (a -> b -> c) -> ((a, b) -> c)
uncurry f p             =  f (fst p) (snd p)

-- | Swap the components of a pair.
swap                    :: (a,b) -> (b,a)
swap (a,b)              = (b,a)
|])
```