{-# LANGUAGE TypeFamilies, TemplateHaskell, EmptyDataDecls, TypeOperators #-}
{- |
Module : Type.Spine
Copyright : (c) The University of Kansas 2011
License : BSD3
Maintainer : nicolas.frisby@gmail.com
Stability : experimental
Portability : see LANGUAGE pragmas (... GHC)
The spine-view on types.
-}
module Type.Spine (qK, Spine, TypeName, (:@), spineType) where
import Type.Spine.Kinds (parseK_, forallAppsK)
import Type.Spine.Stage0
import Language.Haskell.TH (Kind(ArrowK), tySynInstD, varT, mkName)
import Language.Haskell.TH.Quote (QuasiQuoter(..))
import Control.Monad ((<=<))
-- | @[qK|...|]@ is the a type that takes one parameter of the corresponding
-- kind. (The name is an encoding of that parameter's kind based on prefix
-- notation for application.)
qK :: QuasiQuoter
qK = QuasiQuoter (error "Type.Spine.qK Exp")
(error "Type.Spine.qK Pat")
(kTypeG <=< parseK_) (error "Type.Spine.qK Dec")
infixl 9 :@
-- | A type-level application.
data tc :@ t
fmap concat $ forallAppsK $ \ak k ->
let kq = kTypeG k; aq = kTypeG ak; fq = kTypeG $ ArrowK ak k
[f, a] = map (varT . mkName) ["f", "a"]
in (:[]) `fmap` tySynInstD ''Spine [[t| $kq ($f $a) |]] [t| $fq $f :@ $aq $a |]
fmap concat $ mapM spineType
[''Bool, ''Char, ''Double, ''Float, ''Int, ''Integer, ''Ordering,
''(), ''(,), ''(,,), ''(,,,), ''(,,,,),
''IO, ''[], ''Maybe, ''(->), ''Either]