7

In the following instance of Monad:

instance Monad ((->) r) where return = const f >>= k = \ r -> k (f r) r 

Is this forcing k to be a function of two parameters? And if so, why would you want to pass (f r) AND r to k?

3
  • You might like the Monads as Containers section on the reader monad (search for "reader"). Commented Sep 1, 2015 at 21:00
  • Yes k is a function a -> r -> b. r is the only instance of r you have and f r is the only way to get an a so you don't have much choice. Commented Sep 1, 2015 at 21:02
  • possible duplicate of How to use (->) instances of Monad and confusion about (->) Commented Sep 2, 2015 at 2:40

1 Answer 1

9

Is this forcing k to be a function of two parameters?

Yes. Looking at the definition of Monad, we have

class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b 

Substituting (->) r for m, we have

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

Now, (->) r a is just a weird syntax for r -> a, and similarly for the other cases, so we get

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

So we can see that indeed the second argument to >>= must be a function of (at least) two arguments.

Why? Because a function of two arguments is just a function taking one argument and returning a function of one argument, while the second argument to >>= should be a function taking one argument and returning a value of the monad's type constructor; for the function monad, this value will be a function. Hence the second argument to >>= will be a function of two arguments.

[W]hy would you want to pass (f r) AND r to k?

Partly because it makes the (->) r type fit the uniform structure of a Monad, which is useful for lots of reasons.

Partly k doesn't know which function f you're using. That means that, from k's perspective, the two arguments f r and r really are independent --- k can't calculate one from the other.

Consider this function:

-- | 'f' takes two numbers and adds them together f :: (->) (Int, Int) Int f = fst >>= \ n0 -> snd >>= \ n1 -> return (n0 + n1) 

The function \ n0 -> snd >>= \ n1 -> return (n0 + n1) doesn't care where its argument comes from, or in particular that its argument is the first component of the input. So it needs both the argument n0 and the full input.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.