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 with`lift`

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