module Data.Singletons.Promote.Type ( promoteType, promoteUnraveled ) where
import Language.Haskell.TH.Desugar
import Data.Singletons.Names
import Data.Singletons.Util
import Language.Haskell.TH
promoteType :: Monad m => DType -> m DKind
promoteType = go []
where
go :: Monad m => [DKind] -> DType -> m DKind
go [] (DForallT _tvbs _cxt ty) = go [] ty
go [] (DAppT (DAppT DArrowT (DForallT (_:_) _ _)) _) =
fail "Cannot promote types of rank above 1."
go args (DAppT t1 t2) = do
k2 <- go [] t2
go (k2 : args) t1
go args (DSigT ty ki) = do
ty' <- go [] ty
return $ foldType (DSigT ty' ki) args
go args (DVarT name) = return $ foldType (DVarT name) args
go [] (DConT name)
| name == typeRepName = return DStarT
| name == stringName = return $ DConT symbolName
| nameBase name == nameBase repName = return DStarT
go args (DConT name)
| Just n <- unboxedTupleNameDegree_maybe name
= return $ foldType (DConT (tupleTypeName n)) args
| otherwise
= return $ foldType (DConT name) args
go [k1, k2] DArrowT = return $ addStar (DConT tyFunName `DAppT` k1 `DAppT` k2)
go _ (DLitT _) = fail "Cannot promote a type-level literal"
go args hd = fail $ "Illegal Haskell construct encountered:\n" ++
"headed by: " ++ show hd ++ "\n" ++
"applied to: " ++ show args
promoteUnraveled :: Monad m => DType -> m ([DKind], DKind)
promoteUnraveled ty = do
arg_kis <- mapM promoteType arg_tys
res_ki <- promoteType res_ty
return (arg_kis, res_ki)
where
(_, _, arg_tys, res_ty) = unravel ty