{-# LANGUAGE Trustworthy #-} {-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE TypeSynonymInstances #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE DeriveGeneric #-} module GHC.Generics ( -- * Generic representation types V1, U1(..), Par1(..), Rec1(..), K1(..), M1(..) , (:+:)(..), (:*:)(..), (:.:)(..) -- ** Synonyms for convenience , Rec0, Par0, R, P , D1, C1, S1, D, C, S -- * Meta-information , Datatype(..), Constructor(..), Selector(..), NoSelector , Fixity(..), Associativity(..), Arity(..), prec -- * Generic type classes , Generic(..), Generic1(..) ) where -- We use some base types import GHC.Types import Data.Maybe ( Maybe(..) ) import Data.Either ( Either(..) ) -- Needed for instances import GHC.Classes ( Eq, Ord ) import GHC.Read ( Read ) import GHC.Show ( Show ) -------------------------------------------------------------------------------- -- Representation types -------------------------------------------------------------------------------- -- | Void: used for datatypes without constructors data V1 p -- | Unit: used for constructors without arguments data U1 p = U1 -- | Used for marking occurrences of the parameter newtype Par1 p = Par1 { unPar1 :: p } -- | Recursive calls of kind * -> * newtype Rec1 f p = Rec1 { unRec1 :: f p } -- | Constants, additional parameters and recursion of kind * newtype K1 i c p = K1 { unK1 :: c } -- | Meta-information (constructor names, etc.) newtype M1 i c f p = M1 { unM1 :: f p } -- | Sums: encode choice between constructors infixr 5 :+: data (:+:) f g p = L1 (f p) | R1 (g p) -- | Products: encode multiple arguments to constructors infixr 6 :*: data (:*:) f g p = f p :*: g p -- | Composition of functors infixr 7 :.: newtype (:.:) f g p = Comp1 { unComp1 :: f (g p) } -- | Tag for K1: recursion (of kind *) data R -- | Tag for K1: parameters (other than the last) data P -- | Type synonym for encoding recursion (of kind *) type Rec0 = K1 R -- | Type synonym for encoding parameters (other than the last) type Par0 = K1 P {-# DEPRECATED Par0 "Par0 is no longer used; use Rec0 instead" #-} {-# DEPRECATED P "P is no longer used; use R instead" #-} -- | Tag for M1: datatype data D -- | Tag for M1: constructor data C -- | Tag for M1: record selector data S -- | Type synonym for encoding meta-information for datatypes type D1 = M1 D -- | Type synonym for encoding meta-information for constructors type C1 = M1 C -- | Type synonym for encoding meta-information for record selectors type S1 = M1 S -- | Class for datatypes that represent datatypes class Datatype d where -- | The name of the datatype (unqualified) datatypeName :: t d (f :: * -> *) a -> [Char] -- | The fully-qualified name of the module where the type is declared moduleName :: t d (f :: * -> *) a -> [Char] -- | Class for datatypes that represent records class Selector s where -- | The name of the selector selName :: t s (f :: * -> *) a -> [Char] -- | Used for constructor fields without a name data NoSelector instance Selector NoSelector where selName _ = "" -- | Class for datatypes that represent data constructors class Constructor c where -- | The name of the constructor conName :: t c (f :: * -> *) a -> [Char] -- | The fixity of the constructor conFixity :: t c (f :: * -> *) a -> Fixity conFixity _ = Prefix -- | Marks if this constructor is a record conIsRecord :: t c (f :: * -> *) a -> Bool conIsRecord _ = False -- | Datatype to represent the arity of a tuple. data Arity = NoArity | Arity Int deriving (Eq, Show, Ord, Read) -- | Datatype to represent the fixity of a constructor. An infix -- | declaration directly corresponds to an application of 'Infix'. data Fixity = Prefix | Infix Associativity Int deriving (Eq, Show, Ord, Read) -- | Get the precedence of a fixity value. prec :: Fixity -> Int prec Prefix = 10 prec (Infix _ n) = n -- | Datatype to represent the associativity of a constructor data Associativity = LeftAssociative | RightAssociative | NotAssociative deriving (Eq, Show, Ord, Read) -- | Representable types of kind *. -- This class is derivable in GHC with the DeriveGeneric flag on. class Generic a where -- | Generic representation type type Rep a :: * -> * -- | Convert from the datatype to its representation from :: a -> (Rep a) x -- | Convert from the representation to the datatype to :: (Rep a) x -> a -- | Representable types of kind * -> *. -- This class is derivable in GHC with the DeriveGeneric flag on. class Generic1 f where -- | Generic representation type type Rep1 f :: * -> * -- | Convert from the datatype to its representation from1 :: f a -> (Rep1 f) a -- | Convert from the representation to the datatype to1 :: (Rep1 f) a -> f a -------------------------------------------------------------------------------- -- Derived instances -------------------------------------------------------------------------------- deriving instance Generic [a] deriving instance Generic (Maybe a) deriving instance Generic (Either a b) deriving instance Generic Bool deriving instance Generic Ordering deriving instance Generic () deriving instance Generic ((,) a b) deriving instance Generic ((,,) a b c) deriving instance Generic ((,,,) a b c d) deriving instance Generic ((,,,,) a b c d e) deriving instance Generic ((,,,,,) a b c d e f) deriving instance Generic ((,,,,,,) a b c d e f g) deriving instance Generic1 [] deriving instance Generic1 Maybe deriving instance Generic1 (Either a) deriving instance Generic1 ((,) a) deriving instance Generic1 ((,,) a b) deriving instance Generic1 ((,,,) a b c) deriving instance Generic1 ((,,,,) a b c d) deriving instance Generic1 ((,,,,,) a b c d e) deriving instance Generic1 ((,,,,,,) a b c d e f) -------------------------------------------------------------------------------- -- Primitive representations -------------------------------------------------------------------------------- -- Int data D_Int data C_Int instance Datatype D_Int where datatypeName _ = "Int" moduleName _ = "GHC.Int" instance Constructor C_Int where conName _ = "" -- JPM: I'm not sure this is the right implementation... instance Generic Int where type Rep Int = D1 D_Int (C1 C_Int (S1 NoSelector (Rec0 Int))) from x = M1 (M1 (M1 (K1 x))) to (M1 (M1 (M1 (K1 x)))) = x -- Float data D_Float data C_Float instance Datatype D_Float where datatypeName _ = "Float" moduleName _ = "GHC.Float" instance Constructor C_Float where conName _ = "" -- JPM: I'm not sure this is the right implementation... instance Generic Float where type Rep Float = D1 D_Float (C1 C_Float (S1 NoSelector (Rec0 Float))) from x = M1 (M1 (M1 (K1 x))) to (M1 (M1 (M1 (K1 x)))) = x -- Double data D_Double data C_Double instance Datatype D_Double where datatypeName _ = "Double" moduleName _ = "GHC.Float" instance Constructor C_Double where conName _ = "" -- JPM: I'm not sure this is the right implementation... instance Generic Double where type Rep Double = D1 D_Double (C1 C_Double (S1 NoSelector (Rec0 Double))) from x = M1 (M1 (M1 (K1 x))) to (M1 (M1 (M1 (K1 x)))) = x -- Char data D_Char data C_Char instance Datatype D_Char where datatypeName _ = "Char" moduleName _ = "GHC.Base" instance Constructor C_Char where conName _ = "" -- JPM: I'm not sure this is the right implementation... instance Generic Char where type Rep Char = D1 D_Char (C1 C_Char (S1 NoSelector (Rec0 Char))) from x = M1 (M1 (M1 (K1 x))) to (M1 (M1 (M1 (K1 x)))) = x