How does this getRight :: Either a b -> Maybe b work?
Asked Answered
A

1

5

At HaskellWiki's Do notation considered harmful, section Useful applications, I found:

It shall be mentioned that the do sometimes takes the burden from you to write boring things.

E.g. in

getRight :: Either a b -> Maybe b
getRight y =
   do Right x <- y
      return x

a case on y is included, which calls fail if y is not a Right (i.e. Left), and thus returns Nothing in this case.

Calling fail (Nothing) on a pattern mismatch sounds interesting, so I wanted to try this out. However, the syntax looks wrong - we're not in the Either monad, so how can we extract anything from y?

Indeed, I tried and it gave me "Couldn't match type `Either a' with `Maybe'". So let's use the correct pattern matcher, let in here:

getRight y = do { let (Right x) = y; return x }

That gave me a syntax error "parse error on input `}'". Not that I understand why this doesn't work, but let's write it out in multiline notation:

getRight y = do
    let (Right x) = y
    return x

Ah, that seemed to work - parse at least. However:

*Main> getRight (Right 5)
Just 5
*Main> getRight (Left 5)
Just *** Exception: […]\test.hs:16:13-25: Irrefutable pattern failed for pattern (Data.Either.Right x)
-- `Nothing` was expected

What gives? So my questions are now:

  • What happened here? Why did my semicolon-brace line not work?
  • How to do it correctly (with do, everything else is trivial)?
Aalst answered 26/2, 2014 at 21:59 Comment(4)
The parse error on getRight is because in general, once you switch to explicit braces and semicolons, then all language constructs that are nested inside must use explicit braces and semicolons as well: getRight y = do { let { Right x = y }; return x }Manuscript
@kosmikus: Hm, with that I'm getting a "parse error on input `='"Aalst
No idea. Works for me using ghc-7.4.2, ghc-7.6.3, and ghc-7.8.1-rc1 ...Manuscript
@kosmikus: Uh, never mind. Total beginner mistake: I forgot the first let in ghci let getRight x =Aalst
T
9

The example is probably meant to be

getRight :: Either a b -> Maybe b
getRight y =
   do Right x <- return y -- note: return = Just
      return x

where the pattern match failure calls fail = const Nothing. It is translated into:

getRight y = let ok (Right x) = do {return x}
                 ok _         = fail "pattern mismatch error"
             in return y >>= ok

FWIW most experienced folks seem to think fail as a Monad method was a wart. Check out MonadPlus for a maybe more principled approach to failure.

Trautman answered 26/2, 2014 at 22:20 Comment(2)
That page generally has some problems... for example, whole paragraphs being outdated with a footnote saying that they're outdated (why not just remove it then?).Trypanosome
So only <- notation does call fail on pattern mismatch, let doesn't? Could you maybe show the code that the compiler generates when de-sugaring the do?Aalst

© 2022 - 2024 — McMap. All rights reserved.