3 ms·
The idea is that your individual monad has to say how to compose those functions (and package up values). The type signature of bind and return are is (>>=
by 6gvONxR4sf7o 6y ago
The idea is that your individual monad has to say how to compose those functions (and package up values). The type signature of bind and return are is
(>>=) :: m a -> ( a -> m b) -> m b
return :: a -> m a
In your case f gives you an IO b, which is the first argument to bind (your m a). Then g's output needs packing up, so you use return to take [c] to m [c], giving `return . g :: b -> m [c]`, which will be the second argument to bind (your a -> m b).
That gives you `composed_function x = (f x) >>= (return . g)`, which a "do" block makes potentially clearer :`do {y <- f x; return (g y)}`
- 6gvONxR4sf7o 6y ago(Too late to edit) I'm an idiot. All monads are functors, for which you can just use fmap. `composed_function x = fmap g (f x)` which you can also write as `composed_function x = g <$> f x`, which I now realize someone else has already said. Oops. Anyways the idea is that each sort of "container" defines how to apply functions to it.