module Data.Singletons.CustomStar (
singletonStar,
module Data.Singletons.Prelude.Eq,
module Data.Singletons.Prelude.Bool
) where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax ( Quasi(..) )
import Data.Singletons.Util
import Data.Singletons.Promote
import Data.Singletons.Promote.Monad
import Data.Singletons.Single.Monad
import Data.Singletons.Single.Data
import Data.Singletons.Syntax
import Data.Singletons.Names
import Control.Monad
import Data.Maybe
import Control.Applicative
import Language.Haskell.TH.Desugar
import Language.Haskell.TH.Desugar.Sweeten
import Data.Singletons.Prelude.Eq
import Data.Singletons.Prelude.Bool
singletonStar :: Quasi q
=> [Name]
-> q [Dec]
singletonStar names = do
kinds <- mapM getKind names
ctors <- zipWithM (mkCtor True) names kinds
let repDecl = DDataD Data [] repName [] ctors
[''Eq, ''Show, ''Read]
fakeCtors <- zipWithM (mkCtor False) names kinds
let dataDecl = DataDecl Data repName [] fakeCtors [''Show, ''Read , ''Eq, ''Ord]
promDecls <- promoteM_ $ promoteDataDec dataDecl
singletonDecls <- singDecsM $ singDataD dataDecl
return $ decsToTH $ repDecl :
promDecls ++
singletonDecls
where
getKind :: Quasi q => Name -> q [DKind]
getKind name = do
info <- reifyWithWarning name
dinfo <- dsInfo info
case dinfo of
DTyConI (DDataD _ (_:_) _ _ _ _) _ ->
fail "Cannot make a representation of a constrainted data type"
DTyConI (DDataD _ [] _ tvbs _ _) _ ->
return $ map (fromMaybe DStarK . extractTvbKind) tvbs
DTyConI (DTySynD _ tvbs _) _ ->
return $ map (fromMaybe DStarK . extractTvbKind) tvbs
DPrimTyConI _ n _ ->
return $ replicate n DStarK
_ -> fail $ "Invalid thing for representation: " ++ (show name)
mkCtor :: Quasi q => Bool -> Name -> [DKind] -> q DCon
mkCtor real name args = do
(types, vars) <- evalForPair $ mapM kindToType args
dataName <- if real then mkDataName (nameBase name) else return name
return $ DCon (map DPlainTV vars) [] dataName $
DNormalC (map (\ty -> (NotStrict, ty)) types)
kindToType :: Quasi q => DKind -> QWithAux [Name] q DType
kindToType (DForallK _ _) = fail "Explicit forall encountered in kind"
kindToType (DVarK n) = do
addElement n
return $ DVarT n
kindToType (DConK n args) = foldType (DConT n) <$> mapM kindToType args
kindToType (DArrowK k1 k2) = do
t1 <- kindToType k1
t2 <- kindToType k2
return $ DAppT (DAppT DArrowT t1) t2
kindToType DStarK = return $ DConT repName