Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Nothing >> Just 3 is Nothing in Haskell?

Tags:

haskell

monads

The signature of the >> function in Haskell is this:

(>>) :: m a -> m b -> m b

And the default implementation is:

x >> y = x >>= \_ -> y

By that, I understand that the >> function always returns its right parameter regardless of the value of the left one. The lambda is not even caring what the value of the left parameter (x) is. Then, why is Nothing >> Just 3 equal to Nothing? Shouldn't it just return Just 3, since that is the value of the argument on the right?

I know that any Just value, will return Nothing, when associated with a Nothing, but in this case the Nothing is not even being captured by the lambda. What am I missing?

Bonus question, >>= is called bind. What is >> called?

Thanks.

like image 595
Buzu Avatar asked Apr 17 '14 18:04

Buzu


People also ask

What is just and nothing in Haskell?

The type has two constructors, Just a and Nothing . When a type has multiple constructors, it means that a value of the type must have been constructed with just one of the possible constructors. For this type, a value was either constructed via Just or Nothing , there are no other (non-error) possibilities.

Can a Haskell function return nothing?

No. However, you can have functions that return a trivial value.

What does ++ do Haskell?

The ++ operator is the list concatenation operator which takes two lists as operands and "combines" them into a single list.

What does () mean in Haskell?

() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .


3 Answers

Because the bind is not even caring what the value of the lambda is!

Just x  >>= f = f x
Nothing >>= _ = Nothing

Note the (Nothing >>=) does not evaluate its second argument.

like image 77
leftaroundabout Avatar answered Sep 29 '22 01:09

leftaroundabout


To really understand what (>>) does in this case you have to look at the definition of (>>=) for Maybe:

(Just x) >>= k      = k x
Nothing  >>= _      = Nothing

Nothing >>= k evaluates to Nothing regardless of what the k function is. In the specific case of (>>), k just happens to be \_ -> y.

like image 36
duplode Avatar answered Sep 29 '22 01:09

duplode


By that, I understand that the >> function always returns its right parameter regardless of the value of the left one

This is the source of your confusion!

m >>= f invokes f for values it "finds inside" m, "combining" the results (where what it means for values to be "found inside" a monadic value and what it means to "combine" are monad-specific).

m >> n has to be equivalent to m >>= \_ -> n. So for each value it finds inside m, it will invoke \_ -> n on it. But Nothing in the Maybe monad doesn't have any values "inside" it. So \_ -> n can't ever even be invoked on anything in order to ignore it and return n! So Nothing >>= \_ -> n has to return something that doesn't depend on n, since it has no way of calling the function to obtain n. There also aren't any values of the wrapped type floating around in this context, so the only option available is simply Nothing.

So rather than your intuition for understanding >> being that it ignores the left and returns what's on the right, it's better to think that it takes the "monadic structure" of what's on the left and binds that with the monadic value on the right. "Monadic structure" is a hand-wavey term for "everything that defines a monadic value other than the values inside it".

listA >> listB does the same thing regardless of the particular values in listA, but it matters how many elements are in it. ioA >> ioB does the same thing regardless of what value is produced by executing ioA, but it matters side effects were done to produce it. stateA >> stateB ignores the value produced by stateA, but sends the current state to stateB. And maybeA >> maybeB does the same thing regardless of the particular value inside maybeA, but it matters whether there is a value or not. Note that the list case behaves very similarly to Maybe; if listA is empty then listA >> listB has to be empty too.

As for your bonus question, when I'm reading code to myself (in my head) I tend to pronounce both >>= and >> as "bind"; when I'm looking at the code as well as pronouncing it there's enough non-verbal awareness of the context that this ambiguity doesn't matter. I actually don't know what I would say to talk aloud with someone about >>= and >>; maybe "bind" and "forgetful bind"?

like image 36
Ben Avatar answered Sep 29 '22 00:09

Ben