singletons-1.0: src/Data/Singletons/Single/Type.hs
{- Data/Singletons/Single/Type.hs
(c) Richard Eisenberg 2013
eir@cis.upenn.edu
Singletonizes types.
-}
module Data.Singletons.Single.Type where
import Language.Haskell.TH.Desugar
import Language.Haskell.TH.Syntax
import Data.Singletons.Names
import Data.Singletons.Single.Monad
import Data.Singletons.Promote.Type
import Data.Singletons.Util
import Control.Monad
data TopLevelFlag = TopLevel | NotTopLevel
singType :: TopLevelFlag
-> DType -- the promoted version of the thing classified by...
-> DType -- ... this type
-> SgM ( DType -- the singletonized type
, Int -- the number of arguments
, [Name] ) -- the names of the tyvars used in the sing'd type
singType top_level prom ty = do
let (cxt, tys) = unravel ty
args = init tys
num_args = length args
cxt' <- mapM singPred cxt
arg_names <- replicateM num_args (qNewName "t")
let args' = map (\n -> singFamily `DAppT` (DVarT n)) arg_names
res' = singFamily `DAppT` (foldl apply prom (map DVarT arg_names))
tau = ravel (args' ++ [res'])
ty' <- case top_level of
TopLevel -> do
prom_args <- mapM promoteType args
return $ DForallT (zipWith DKindedTV arg_names prom_args)
cxt' tau
-- don't annotate kinds. Why? Because the original source
-- may have used scoped type variables, and we're just
-- not clever enough to get the scoped kind variables right.
-- (the business in bindTyVars gets in the way)
-- If ScopedTypeVariables was actually sane in patterns,
-- this restriction might be able to be lifted.
NotTopLevel -> return $ DForallT (map DPlainTV arg_names)
cxt' tau
return (ty', num_args, arg_names)
singPred :: DPred -> SgM DPred
singPred = singPredRec []
singPredRec :: [DType] -> DPred -> SgM DPred
singPredRec ctx (DAppPr pr ty) = singPredRec (ty : ctx) pr
singPredRec _ctx (DSigPr _pr _ki) =
fail "Singling of constraints with explicit kinds not yet supported"
singPredRec _ctx (DVarPr _n) =
fail "Singling of contraint variables not yet supported"
singPredRec ctx (DConPr n)
| n == equalityName
= fail "Singling of type equality constraints not yet supported"
| otherwise = do
kis <- mapM promoteType ctx
let sName = singClassName n
return $ foldl DAppPr (DConPr sName) (map kindParam kis)