Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Expression Equivalents

Tags:

haskell

I'm a very new Haskell learner. I have a working expression:

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

which appears to work perfectly (I'm using the Parsec package, but I hope this question has nothing to do with its functionality, as far as I know <|> is a Parsec-defined infix operator). parseA and parseB both have the Parser Foo monad type, as does the whole expression.

Based on what I've read so far, it seems this should be equivalent to

do return (try parseA <|> parseB)

and

do return $ try parseA <|> parseB

but none of the latter compile, they complain of mismatched types (errors below).

My other attempt to rewrite this, as

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

seems to work. But if I've misunderstood this too, please say.

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


Errors (in case this is relevant, though fwiw I'm not looking to 'fix' my code - I have a working version, I'm looking 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)
like image 302
Ian Avatar asked Jan 04 '15 02:01

Ian


People also ask

What is an expression in Haskell?

You should verify with a Haskell grammar specification. – Mateen Ulhaq. Jul 28, 2020 at 23:35. 3. An expression is any piece of code that results in a value (e.g. 8 or 1+1 or \x -> x*2 ).

Where vs let?

It is important to know that let ... in ... is an expression, that is, it can be written wherever expressions are allowed. In contrast, where is bound to a surrounding syntactic construct, like the pattern matching line of a function definition.

What does operator mean Haskell?

Haskell provides special syntax to support infix notation. An operator is a function that can be applied using infix syntax (Section 3.4), or partially applied using a section (Section 3.5).


1 Answers

Do Notation Desugaring

The rules for do notation desugaring imply that

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

is equivalent to

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

($) versus (>>=)

Since (=<<) is a flipped version of (>>=), both are equivalent to

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

This implies 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 -> m b) -> m a -> m b

You can see that ($) is not a replacement for (=<<), but perhaps you can also see that they are somewhat similar. One way to look at it is that (=<<) – and thus also (>>=) – is a kind of function application that applies "monadic functions" of type a -> m b for some Monad m to "monadic values" of type m a for some Monad m, whereas ($) is the usual kind of function application that applies functions of type a -> b to values of type a.

Monad Laws

One of the monad laws is that

k >>= return = k

This implies that

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

can also be written as

try parseA <|> parse B

which means your original form using do notation can also be written that way.

like image 77
Rein Henrichs Avatar answered Oct 01 '22 03:10

Rein Henrichs