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. -
a
is 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. -
m
is the base monad, embedded withlift
. -
a
is 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.