Function as an Instance of Monad

haskell, monads

Solution

First, here's the type of `(>>=)`:

(>>=) :: (Monad m) => m a -> (a -> m b) -> m b

Now, with `m` specialized to `((->) r)`:

(>>=) :: ((->) r) a -> (a -> ((->) r) b) -> ((->) r) b

Rewritten with all the function arrows infix:

(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)

Removing some superfluous parentheses:

(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b

At which point it should be much easier to see what's going on: the third argument (of type `r`) is given to the first argument to get something of type `a`, then both that result and the third argument are given to the second argument to get a final result of type `b`.

So, `((->) r)` as a `Monad` represents an extra function argument to every value in that monad, and when monadic values are combined the single "extra" argument is duplicated and given to each input value. Essentially, this creates a "read-only global environment" for monadic values. This interpretation is provided explicitly as the `Reader` monad, which is just a wrapper around `((->) r)`.

Problem

I am having difficulty understanding how a function can be a monad. Function `(->) r` is a monad according to a declaration in `Control.Monad.Instances`: ``` instance Monad ((->) r) where return x = \_ -> x h >>= f = \w -> f (h w) w ``` Even what Miran Lipovača says about it makes me confused: The implementation for `>>=` seems a bit cryptic, but it's really not all that. When we use `>>=` to feed a monadic value to a function, the result is always a monadic value. So in this case, when we feed a function to another function, the result is a function as well. That's why the result starts off as a lambda. All of the implementations of `>>=` so far always somehow isolated the result from the monadic value and then applied the function f to that result. The same thing happens here. To get the result from a function, we have to apply it to something, which is why we do `(h w)` here to get the result from the function and then we apply f to that. f returns a monadic value, which is a function in our case, so we apply it to w as well. The type signature of (>>=) is this: (>>=) :: m a -> (a -> m b) -> m b So I take that `h` is typed as `m a` and `f` as `(a -> m b)`. If a function is `m a`, does it return an `a` type value? or does it return something else taking an `a` type? If the non-monad value of `h` is fed to `f`, then we get: f (h w) Looks fine. Since `f` is a function and has taken its sole argument, it is already a value, no? Since it's a monadic function the value is also a monadic value. Why then does it need another value `w`? Doesn't feeding `w` to `f something` make it non-monadic, i.e., it is not a function any more, no? I also cannot understand why `f something` and `h` take the same argument `w` and return different value types (`m a` and `m b`).

Original source