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?
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?
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.