Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble Understanding Monad (->)

Tags:

haskell

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?

like image 343
GreenSaguaro Avatar asked Sep 01 '15 20:09

GreenSaguaro


People also ask

Why are monads so hard to explain?

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.

What is a monad in simple terms?

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.

What problem do monads solve?

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.

What is a monad example?

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.


1 Answers

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.

like image 51
Jonathan Cast Avatar answered Sep 24 '22 07:09

Jonathan Cast