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
?
A monad is useful for other things besides input and output. A monad is difficult to understand because most of the articles about monads go into too much detail or too little detail.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
Monad is a simple and powerful design pattern for function composition that helps us to solve very common IT problems such as input/output, exception handling, parsing, concurrency and other. Application becomes less error prone.
Monads are simply a way to wrapping things and provide methods to do operations on the wrapped stuff without unwrapping it. For example, you can create a type to wrap another one, in Haskell: data Wrapped a = Wrap a. To wrap stuff we define return :: a -> Wrapped a return x = Wrap x.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With