"<-" and related values

Say I wrote the following amazin code snippet:

 func = do a <- Just 5 return a 

This is pretty pointless, I know. Here a is 5 , and func returns Just 5 .

Now I rewrite my awesome (but meaningless) function:

 func' = do a <- Nothing return a 

This function returns Nothing , but what the hell is a ? There is nothing to extract from the Nothing value, but the program does not whine when I do something like this:

 func'' = do a <- Nothing b <- Just 5 return $ a+b 

It’s just hard for me to see what is really happening. What is a ? In other words: what does <- really do? Saying this, "extracts the meaning from the right side and connects it with the left side", obviously, simplifies it too much. What am I not getting?

Thanks:)

+6
source share
5 answers

Let's try and draw an annotation of this last example.

 func'' = Nothing >>= (\a -> Just 5 >>= (\b -> return $ a+b)) 

Now let's see how β†’ = is defined for Maybe. This is a prelude:

 instance Monad Maybe where (Just x) >>= k = kx Nothing >>= k = Nothing return = Just fail s = Nothing 

So Nothing >>= foo just Nothing

+11
source

The answer is to define an instance of Monad Maybe :

 instance Monad Maybe where (Just x) >>= k = kx Nothing >>= _ = Nothing (Just _) >> k = k Nothing >> _ = Nothing return = Just 

Your func'' translates to:

 Nothing >>= (\a -> (Just 5 >>= (\b -> return (a+b)))) 

From the definition (>>=) you can see that the first Nothing simply passed to the result.

+6
source

Take a look at Maybe monad definition.

 instance Monad Maybe where return = Just Just a >>= f = fa Nothing >>= _ = Nothing 

And discolor the do -notation in your function:

 func' = Nothing >>= \a -> return a 

The first argument >>= is Nothing , and the definition above shows that >>= simply ignores the second argument. So we get:

 func' = Nothing 

Since the function \a -> ... never called, a never assigned. Therefore, the answer: a is not even reached.


As for desugaring do notation, here is a brief overview of how it was done (there was one simplification - processing fail , i.e. templates that do not match):

 do {a; rest} β†’ a >> do rest 

Note that >> usually implemented in terms of >>= as a >>= \_ -> do rest (i.e. the second function simply ignores the argument).

 do {p <- a; rest} β†’ a >>= \p -> do rest do {let x = a; rest} β†’ let x = a in do rest 

And finally:

 do {a} = a 

Here is an example:

 main = do name <- getLine let msg = "Hello " ++ name putStrLn msg putStrLn "Good bye!" 

desugars:

 main = getLine >>= \name -> let msg = "Hello " ++ name in putStrLn msg >> putStrLn "Good bye!" 

And to do this for those who are curious, here is the "correct" translation do {p <- a; rest} do {p <- a; rest} (taken directly from the Haskell report):

 do {pattern <- a; rest} β†’ let ok pattern = do rest ok _ = fail "error message" in a >>= ok 
+5
source

Nothing is not really β€œnothing,” it is actually the possible meaning of something in the Maybe monad:

 data Maybe t = Nothing | Just t 

That is, if you have something like Maybe t for some type t , it can be Just x (where x is something like t ) or Nothing ; in this sense, Maybe just extends t to have another possible value, Nothing . (It has other properties because it is monad , but that really doesn't concern us, except for the syntactic sugar do and <- .)

+2
source

Take your example:

 func = do a <- Just 5 return a 

As in other programming languages, you can break it into two parts to fit "what has been done so far" and "what remains to be done." For example, we can make a gap between Just 5 and

 a <- ... return a 

In many popular programming languages, you expect Just 5 be added to the a variable, and the code will continue.

Haskell is doing something else. The "rest of the code" can be thought of as a function that describes what you will do with a if you had a value to enter it. This function is then applied to Just 5 . But it is not applied directly. It is applied using any definition of >>= , depending on the type of your expression. For Maybe , >>= is defined so that when working with Just X , the "rest of the code" function is applied to X But it is also defined so that when working with Nothing , the "rest of the code" function is simply ignored and Nothing returned.

Now we can interpret your other example.

 func'' = do a <- Nothing b <- Just 5 return $ a+b 

Break it into Nothing and:

  a <- ... b <- Just 5 return $ a+b 

As I said above, this block of code can be considered as a function applied to the possible value of a . But it is used with Nothing , in which case >>= is defined as ignoring the "rest of the code" and simply returns Nothing . And this is the result that you got.

+1
source

Source: https://habr.com/ru/post/913495/


All Articles