definition module StateMonad

// a general-purpose state monad (implemented by macros)

:: StateM state a
	:== !state -> *(a, !state)

// basic monad operations as macro definitions

//result :: a -> StateM .state a
result x :== \state -> (x, state)

//(>>>=) infixl :: (StateM .state a) (a -> StateM .state b) -> StateM .state b
(>>>=) infixl 
(>>>=) ma f  :== \state -> let (a, state`) = ma state in f a state`

//(>>>) infixl :: (StateM .state a) (StateM .state b) -> StateM .state b
(>>>) infixl
(>>>) ma mb :== \state -> let (_, state`) = ma state in mb state`

// more monad operations

mapl			:: (a -> StateM state b) ![a]				->	StateM state [b]
mfoldr			:: (a -> b -> StateM state b) b ![a]		->	StateM state b
runState		:: state !(StateM state a)					-> (a,state)
sequence		:: ![StateM s a]							-> StateM s [a]
mmap			:: (a -> b) (StateM s a)					-> StateM s b
mWhile			:: (StateM s Bool) (StateM s a)				-> StateM s [a]


skip :== result nothing

// an IF-THEN-ELSE construct, which is more readable if the branches are large

IF guard _ thenBranch _ elseBranch :== if guard thenBranch elseBranch
THEN :== 0
ELSE :== 0

// 'nothing' is used when a monadic operation has no real result
// and thus is a 'side-effect'.

nothing :: nothing

// The onlyIf function only executes its monad argument if the
// boolean is true. Otherwise, nothing is done (result nothing)

onlyIf :: !Bool (StateM .env nothing) -> StateM .env nothing

