Suppose I want a computation that evaluates expressions with variables. I would like it to look variables up in the env passed to its runner, and also have some kind of state and a log. I take an algebra, pepper it with RWS
and I'm done.
Except that lookup
returns Maybe
.
So I need a monad stack.
λ type EvalA = MaybeT (RWS () () ()) ()
λ runRWS (runMaybeT (MaybeT (return (Just ())) :: EvalA )) () ()
(Just (),(),())
λ runRWS (runMaybeT (MaybeT (return Nothing) :: EvalA )) () ()
(Nothing,(),())
So far so good. But the type is somewhat messy: a transformer on top of a transformer on top of Identity
. Why not flip this.
λ type EvalB = RWST () () () Maybe ()
λ runRWST (return () :: EvalB) () ()
Just ((),(),())
λ runRWST (Nothing :: EvalB) () ()
<interactive>:12:10: error:
• Couldn't match type ‘Maybe a0’ with ‘RWST () () () Maybe ()’
Expected type: EvalB
Actual type: Maybe a0
..........
λ -- ...?
Putting aside that having a Nothing
plus a log is better than having a Nothing
alone, how can I obtain a Nothing
from EvalB
?