MonadLab-0.0.1: MonadLab/CommonTypes.hs
{-# LANGUAGE TemplateHaskell #-}
module MonadLab.CommonTypes (
Layer(..),
ErrorName, StateName, EnvName, WriterName,
LayerType(..),
layerType, hasLayerType,
Monad, MonadName, MonadTypeCon,
ReturnExpQ, BindExpQ, LiftExpQ, JoinExpQ, RunExpQ, NonProperMorphismExpQ,
MonadTransformer,
LayerNPM,
getTypeCon, getReturn, getBind, getLayerNPMs, getBaseLift, getJoin,
int, bool, string,
composition, arrow
) where
import Prelude hiding (Monad)
import Language.Haskell.TH
{- |
The Layer data type.
A monad is constructed from a list of layers.
Each layer adds a corresponding set of non-proper
morphisms (npms) for use in the monad. The non-proper morphisms
can be thought of as the interface of the monad or
primitives in the constructed monad \"language\".
-}
data Layer
{- | The Io layer.
Adds an npm for IO operations.
-}
= Io
{- | The List layer.
Adds an npm for expressing nondeterministic computation.
-}
| List
{- | The Error (or Exception) layer.
Adds npms for exception throwing/handling.
-}
| ErrorT ErrorName TypeQ
{- | The State layer.
Adds npms for the manipulation of a mutable state.
-}
| StateT StateName TypeQ
{- | The Environment layer.
Adds npms for reading/pre-setting an immutable environment.
-}
| EnvT EnvName TypeQ
{- | The Writer layer.
Adds npms for the production/manipulation of sequenced output.
-}
| WriterT WriterName TypeQ
{- | The Continuation layer.
f no List layer is included in the li , then the corresponding Layer transformers are composed Adds an npm for accessing current continuation to facilate
continuation passing style programming.
-}
| ContT TypeQ
type ErrorName = String
type StateName = String
type EnvName = String
type WriterName = String
data LayerType = IoLayerType
| ListLayerType
| StateLayerType
| EnvLayerType
| ErrorLayerType
| WriterLayerType
| ContLayerType
deriving Eq
layerType :: Layer -> LayerType
layerType Io = IoLayerType
layerType List = ListLayerType
layerType (StateT _ _) = StateLayerType
layerType (EnvT _ _) = EnvLayerType
layerType (ErrorT _ _) = ErrorLayerType
layerType (WriterT _ _) = WriterLayerType
layerType (ContT _) = ContLayerType
hasLayerType :: LayerType -> Layer -> Bool
hasLayerType lt l = layerType l == lt
----------------------------------------------
-- | The monad type. Each component contains abstract
-- syntax of the Haskell code to implement the monad.
-- Components are (code for the data type, code for the return, code for the
-- bind, code for the non-proper morphisms, code for the monad lifting)
type Monad = (MonadTypeCon, ReturnExpQ, BindExpQ, [LayerNPM], LiftExpQ)
-- | The name of monad type constructor identifier
type MonadName = String
-- | The monad type constructor type.
type MonadTypeCon = TypeQ -> TypeQ
-- Data types for monad code components.
-- All are type synonyms for ExpQ
-- | Code for a monad return
type ReturnExpQ = ExpQ
-- | Code for a monad bind
type BindExpQ = ExpQ
-- | Code for a monad lifting
type LiftExpQ = ExpQ
-- | Code for a monad join
type JoinExpQ = ExpQ
-- | Code for a monad run (evaluation)
type RunExpQ = ExpQ
-- | Code for a monad non-proper morphism
type NonProperMorphismExpQ = ExpQ
-- | Data type to hold a layer's non-proper morphisms
type LayerNPM = (Layer , [NonProperMorphismExpQ])
-- | Monad transformer data type
type MonadTransformer = Monad -> Monad
-- | Type constructor accessor
getTypeCon :: Monad -> MonadTypeCon
getTypeCon (tc, _, _,_, _) = tc
-- | Return accessor
getReturn :: Monad -> ReturnExpQ
getReturn (_, ret, _, _, _) = ret
-- | Bind accessor
getBind :: Monad -> BindExpQ
getBind (_, _, bind, _, _) = bind
-- | Layers accessor
getLayerNPMs :: Monad -> [LayerNPM]
getLayerNPMs (_, _, _, lnpms, _) = lnpms
-- | Base monad lifting accessor
getBaseLift :: Monad -> LiftExpQ
getBaseLift (_, _, _, _, baseLift) = baseLift
-- | Join accessor
getJoin :: Monad -> JoinExpQ
getJoin m = let return = getReturn m
bind = getBind m
in [| \x -> $bind x (\a -> a) |]
----------------------------------------------
-- | Short hand for [t| Int |], [t| Bool |], and [t| String |]
int, bool , string :: TypeQ
int = [t| Int |]
bool = [t| Bool |]
string = [t| String |]
-- | Definition of composition function for use in TH expressions
composition :: ExpQ
composition = [| \f -> \g -> \x -> f (g x) |]
-- | Convenience function for expressing type @t -> t'@ in TH
arrow :: TypeQ -> TypeQ -> TypeQ
arrow t1 t2 = appT (appT (conT $ mkName "(->)") t1) t2
-- Note the weird use of prefix notation here; this is to
-- work around a bug in TH's pretty printer