Control.Monad.Operational
Contents
Description
Implement monads by specifying primitive instructions and their operational semantics.
This package is based on the "The Operational Monad Tutorial", published in Issue 15 of The Monad.Reader http://themonadreader.wordpress.com/.
You are reading the API reference. For more thorough documentation including design and implementation notes as well as a correctness proof, please consult the included doc/Documentation.html.
This API reference includes only basic example code. More intricate examples are available in the doc/examples directory.
Basic usage
type Program instr a = ProgramT instr Identity aSource
The abstract data type 'Program instr a' represents programs.
- The type constructor
instr :: * -> *indexes the primitive instructions. -
ais the return type of a program.
is always a monad and
automatically obeys the monad laws.
Program instr
Example
Stack machine from "The Operational Monad Tutorial".
data StackInstruction a where
Push :: Int -> StackInstruction ()
Pop :: StackInstruction Int
type StackProgram a = Program StackInstruction a
interpret :: StackProgram a -> (Stack Int -> a)
interpret = eval . view
where
eval :: Prompt StackInstruction a -> (Stack Int -> a)
eval (Push a :>>= is) stack = interpret (is ()) (a:stack)
eval (Pop :>>= is) (a:stack) = interpret (is a ) stack
eval (Return a) stack = a
Note that since Prompt is a GADT, the type annotation for eval is mandatory.
Monad transformer
data ProgramT instr m a Source
The abstract data type represents programs.
ProgramT instr m a
- The type constructor
instr :: * -> *indexes the primitive instructions. -
mis the base monad, embedded withlift. -
ais the return type of a program.
is a monad transformer and
automatically obey both the monad and the lifting laws.
ProgramT instr m
viewT :: Monad m => ProgramT instr m a -> m (PromptT instr m a)Source
View function for inspecting the first instruction.
Example
List monad transformer.
data PlusI m a where
Zero :: PlusI m a
Plus :: ListT m a -> ListT m a -> PlusI m a
type ListT m a = ProgramT (PlusI m) m a
runList :: Monad m => ListT m a -> m [a]
runList = eval <=< viewT
where
eval :: Monad m => PromptT (PlusI m) m a -> m [a]
eval (Return x) = return [x]
eval (Zero :>>= g) = return []
eval (Plus m n :>>= g) =
liftM2 (++) (runList (m >>= g)) (runList (n >>= g))
Note that since Prompt is a GADT, the type annotation for eval is mandatory.