Question

I am currently learning the basics of computations with monads. I have been examining snippets of code and I believe I have an idea what they do, but I may need some clarification. It involves the instance of a Maybe monad.

There is some function that attempts to calculate the tail and one that attempts to calculate the head of a list. The functions below produce equivalent results when called with the list [1,2,3,4,5] = Just 3

The function func3 appears to 'skip' an extra computation step over func2. Am I correct saying that func3 takes the result of the computation and feeds it into the tail computation below, which then calculates its tail, then passes the result of that computation to the function below which computes the head?

If so, then why do we need to have func2 ignoring the result of the initial computation? It seems to me as if it runs the myTail xs computation, then passes its value in to the function, which uses the initial list instead of the result of the tail computation.

So therefore, is this just a redundant step to illustrate each of a, b, c? I assume that func3 is also equivalent to func1, only the top most computation is a.

Many thanks all.

--computes head
myHead :: [a] -> Maybe a
myHead [] = Nothing
myHead (x:xs) = Just x

--computes tail
myTail :: [a] -> Maybe [a]
myTail [] = Nothing
myTail (x:xs) = Just xs


--below are all equivalent

func1 :: [a] -> Maybe a
func1 xs =
  do a <- myTail xs
     b <- myTail a
     c <- myHead b
     return c


func2 :: [a] -> Maybe a
func2 xs = 
   myTail xs >>=
     (\a -> myTail xs >>=
       (\b -> myTail b >>=
         (\c -> myHead c)))


func3 :: [a] -> Maybe a
func3 xs = 
   myTail xs >>=
     (\a -> myTail a >>=
       (\b -> myHead b))
Was it helpful?

Solution 2

Yes you are right. The 3 functions func1, func2, func3 do the same thing. func2 has one extra step which is unnecessary. func1 uses do notation to express exactly the same computation as func3. However the a, b and c of func1 and func2 are not the same.

OTHER TIPS

The equivalent of the do notation of func1 in canonical monad operations, is made moving the variable to the argument position of the following lambda

func4 :: [a] -> Maybe a
func4 xs = 
   myTail xs >>= \a ->
       myTail a >>= \b ->
           myHead b >>= \c ->
               return c 

In fact the last lambda does not change the previous line result, so it can be suppressed leading to func3.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top