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. -
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.