Fri Aug 14 17:39:49 EDT 2015
For monad m, is there a way to write a class that has these two
maybeJoin :: m (m t) -> m t
maybeJoin :: m t -> m t
I can't get this to work because the second pattern also matches the
first one, and also other type unification issues I don't understand.
This arises in a DSL with operations like:
add :: t -> t -> m t
Where I would like to use nested expressions as well by defining
"evaluation order" on functions with signatures:
t -> m t -> m t
m t -> t -> m t
m t -> m t -> m t
I want it to pick the right one automatically.
It's easy to define the last one
add' a b = join $ liftM2 f a b
And then insert return whenever needed.
Maybe look for "join $ liftM2" which seems to be an indicator of this
kind of problem popping up elsewhere..
Alternatively, use m t -> m t -> m t for everything, but replace bind
a <= ...
a' <- ...
let a = return a'
This way it is guaranteed that the monadic operation has executed,
e.g. if a is used multiple times, the computation that produced a'
only ran once.
... >>= $ \x ->
... >>= $ \y ->
Could change that to >>>= where
(>>>=) :: Monad m => m a -> (m a -> m b) -> m b
m >>>= f = m >>= (f . return)