Haskell Equivalents

I am a very new student of Haskell. I have a working expression:

do x <- try parseA <|> parseB return x 

which works fine (I use the Parsec package, but I hope this question has nothing to do with its functionality, as far as I know, <|> is an infix operator defined by Parsec). parseA and parseB both have the Parser Foo monad type, like the whole expression.

Based on what I have read so far, it seems like this should be equivalent

 do return (try parseA <|> parseB) 

and

 do return $ try parseA <|> parseB 

but none of the latter compiles, they complain about inappropriate types (errors below).

My other attempt to rewrite this as

 (try parseA <|> parse B) >>= return 

seems to work. But if I also misunderstood this, please tell me.

So my question is, can someone explain why the first three are different. I am confused why they are not equivalent. What am I missing?


Errors (in case this matters, although fwiw I don’t want to “fix” my code - I have a working version, I want to understand how the versions differ):

 do return (try parseA <|> parseB) 

gives

 parse.hs:76:11: Couldn't match expected type 'Foo' with actual type 'Text.Parsec.Prim.ParsecT [Char] () Data.Functor.Identity.Identity Foo' 

and

 do return $ try parseA <|> parseB 

gives

 parse.hs:76:3: Couldn't match type 'Text.Parsec.Prim.ParsecT [Char] () Data.Functor.Identity.Identity Foo' with 'Foo' Expected type: Parser Foo Actual type: Text.Parsec.Prim.ParsecT String () Data.Functor.Identity.Identity (Text.Parsec.Prim.ParsecT [Char] () Data.Functor.Identity.Identity Foo) 
+8
haskell
source share
1 answer

Notation Desauration

The rules for designating the desugging of a notation imply that

 do x <- try parseA <|> parseB return x 

equivalently

 (try parseA <|> parse B) >>= return 

($) compared to (>>=)

Since (=<<) is a flip version (>>=) , both are equivalent

 return =<< (try parseA <|> parse B) 

This means that the only difference between your correct version and return $ try parseA <|> parse B is the difference between (=<<) and ($) , whose types are:

 ($) :: (a -> b) -> a -> b (=<<) :: (a -> mb) -> ma -> mb 

You can see that ($) not a replacement (=<<) , but perhaps you can also see that they are somewhat similar. One way to look at this is (=<<) - and therefore also (>>=) - is a kind of functional application that applies "monadic functions" like a -> mb for some Monad m to "monadic values "of type ma for some Monad m , while ($) is a common kind of function application that applies functions of type a -> b to values ​​of type a .

Monad Laws

One of the laws of the monad is that

 k >>= return = k 

It follows that

 (try parseA <|> parse B) >>= return 

can also be written as

 try parseA <|> parse B 

which means that your original form, using the designation, can also be written this way.

+11
source share

All Articles