{-# OPTIONS -fglasgow-exts #-} ---------------------------------------------------------------------- -- | -- Module : Data.Tupler -- Copyright : (c) Conal Elliott 2007 -- License : LGPL -- -- Maintainer : conal@conal.net -- Stability : experimental -- Portability : portable -- -- The tuple type constructors (i.e., (,), (,,), etc) are to value types, -- as the /tupler/ type constructors are to type constructors. ---------------------------------------------------------------------- module Data.Tupler ( Pair1(..), Pair2(..) ) where import Data.Typeable -- or AltData.Typeable ? -- | Pairing for unary type constructors. newtype Pair1 f g a = Pair1 {unPair1 :: (f a, g a)} deriving (Eq, Ord, Show) instance (Typeable1 f, Typeable1 g) => Typeable1 (Pair1 f g) where typeOf1 = const $ mkTyConApp (mkTyCon tyConStr) [] where tyConStr = "Data.Tupler.Pair1" ++ tcStringSP (undefined :: f Bool) ++ tcStringSP (undefined :: g Bool) -- | Pairing for binary type constructors. newtype Pair2 f g a b = Pair2 {unPair2 :: (f a b, g a b)} deriving (Eq, Ord, Show) instance (Typeable2 f, Typeable2 g) => Typeable2 (Pair2 f g) where typeOf2 = const $ mkTyConApp (mkTyCon tyConStr) [] where tyConStr = "Data.Tupler.Pair2" ++ tcStringSP (undefined :: f Bool Bool) ++ tcStringSP (undefined :: g Bool Bool) ---- Misc -- | Disambuating hack for a function argument. Wrap parens around a string -- if it contains a space. parensIfSpace :: String -> String parensIfSpace str | ' ' `elem` str = "("++str++")" | otherwise = str -- | Extract the type constructor as a string tcString :: Typeable a => a -> String tcString = tyConString . typeRepTyCon . typeOf -- | 'tcString' with disambiguating optional parens tcStringP :: Typeable a => a -> String tcStringP = parensIfSpace . tcString -- | 'tcString' with leading space and optional parens tcStringSP :: Typeable a => a -> String tcStringSP = (' ':) . tcStringP