{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE StandaloneDeriving #-}
module Generics.MRSOP.Base.Metadata where
import Data.Proxy
import Data.SOP.Constraint
import Generics.MRSOP.Util
import Generics.MRSOP.Base.NP
import Generics.MRSOP.Base.Universe
import Generics.MRSOP.Base.Class
type ModuleName = String
type FamilyName = String
type ConstructorName = String
type FieldName = String
infixl 5 :@:
data DatatypeName
= Name String
| DatatypeName :@: DatatypeName
deriving (Eq , Show)
data DatatypeInfo :: [[Atom kon]] -> * where
ADT :: ModuleName -> DatatypeName -> NP ConstructorInfo c
-> DatatypeInfo c
New :: ModuleName -> DatatypeName -> ConstructorInfo '[ c ]
-> DatatypeInfo '[ '[ c ]]
moduleName :: DatatypeInfo code -> ModuleName
moduleName (ADT m _ _) = m
moduleName (New m _ _) = m
datatypeName :: DatatypeInfo code -> DatatypeName
datatypeName (ADT _ d _) = d
datatypeName (New _ d _) = d
constructorInfo :: DatatypeInfo code -> NP ConstructorInfo code
constructorInfo (ADT _ _ c) = c
constructorInfo (New _ _ c) = c :* Nil
data Associativity
= LeftAssociative
| RightAssociative
| NotAssociative
deriving (Eq , Show)
type Fixity = Int
data ConstructorInfo :: [Atom kon] -> * where
Constructor :: ConstructorName -> ConstructorInfo xs
Infix :: ConstructorName -> Associativity -> Fixity -> ConstructorInfo '[ x , y ]
Record :: ConstructorName -> NP FieldInfo xs -> ConstructorInfo xs
constructorName :: ConstructorInfo con -> ConstructorName
constructorName (Constructor c) = c
constructorName (Infix c _ _) = c
constructorName (Record c _) = c
data FieldInfo :: Atom kon -> * where
FieldInfo :: { fieldName :: FieldName } -> FieldInfo k
deriving instance Show (FieldInfo atom)
deriving instance (All (Compose Show FieldInfo) code)
=> Show (ConstructorInfo code)
deriving instance (All (Compose Show ConstructorInfo) code)
=> Show (DatatypeInfo code)
class (Family ki fam codes) => HasDatatypeInfo ki fam codes
| fam -> codes ki where
datatypeInfo :: Proxy fam -> SNat ix -> DatatypeInfo (Lkup ix codes)
datatypeInfoFor :: forall ki fam codes ix ty
. ( HasDatatypeInfo ki fam codes
, ix ~ Idx ty fam , Lkup ix fam ~ ty , IsNat ix)
=> Proxy fam -> Proxy ty -> DatatypeInfo (Lkup ix codes)
datatypeInfoFor pf pty = datatypeInfo pf (getSNat $ proxyIdx pf pty)
where
proxyIdx :: Proxy fam -> Proxy ty -> Proxy (Idx ty fam)
proxyIdx _ _ = Proxy
constrInfoLkup :: Constr sum c -> DatatypeInfo sum -> ConstructorInfo (Lkup c sum)
constrInfoLkup c = go c . constructorInfo
where
go :: Constr sum c -> NP ConstructorInfo sum -> ConstructorInfo (Lkup c sum)
go CZ (ci :* _) = ci
go (CS c0) (_ :* cis) = go c0 cis
constrInfoFor :: (HasDatatypeInfo ki fam codes)
=> Proxy fam
-> SNat ix
-> Constr (Lkup ix codes) c
-> ConstructorInfo (Lkup c (Lkup ix codes))
constrInfoFor pfam six c = constrInfoLkup c (datatypeInfo pfam six)