type-spine-0.1: Type/Spine/TH.hs
{-# LANGUAGE TemplateHaskell #-}
{- |
Module : Type.Spine.TH
Copyright : (c) The University of Kansas 2011
License : BSD3
Maintainer : nicolas.frisby@gmail.com
Stability : experimental
Portability : see LANGUAGE pragmas (... GHC)
Template Haskell in support of the spine-view on types.
-}
module Type.Spine.TH where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax
-- | A TemplateHaskell-lifter for 'NameG's.
liftNameG :: Name -> Q Exp
liftNameG n = do
TyConI (DataD _ (Name occ (NameG _ pkg mod)) _ _ _) <- reify n
[| mkNameG_tc $(stringE $ pkgString pkg) $(stringE $ modString mod) $(stringE $ occString occ) |]
-- | Returns the kinds of a type constructor's type paratemers and range.
tyConSignature :: Name -> Q ([Kind], Kind)
tyConSignature n = do
let bad = fail "Type.Spine.TH.tyConSignature expects the name of a data/newtype/data family"
i <- reify n
case i of
TyConI dec -> case dec of
DataD _ _ tvbs _ _ -> return (map tvb_kind tvbs, StarK)
NewtypeD _ _ tvbs _ _ -> return (map tvb_kind tvbs, StarK)
FamilyD DataFam _ tvbs mk -> return (map tvb_kind tvbs, maybe StarK (peel tvbs) mk)
where peel [] k = k
peel (_ : l) (ArrowK _ r) = peel l r
peel _ _ = error "Type.Spine.TH: bad FamilyD kind"
_ -> bad
PrimTyConI _ i _ -> return (replicate i StarK, StarK)
_ -> bad
tvb_kind :: TyVarBndr -> Kind
tvb_kind (PlainTV _) = StarK
tvb_kind (KindedTV _ k) = k