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.