Haskell - Strange do block behavior
Asked Answered
K

1

6

While reading the Haskell Wikibook about MonadPlus, I found the following function which basically takes a Char and a String and returns Just (char,tail) if such char is equal the string head, or Nothing otherwise:

char :: Char -> String -> Maybe (Char, String)
char c s = do
  let (c':s') = s
  if c == c' then Just (c, s') else Nothing

and they explain that let (c':s') = s will not produce an exception, cause it is in a do block which would evaluate to Nothing when the pattern fails, but, that isn't the case, because when I tried it:

*Main> char 'a' ""
*** Exception: exercice2.hs:5:7-17: Irrefutable pattern failed for pattern (c' : s')

So I had to rewrite it to:

char' :: Char -> String -> Maybe (Char, String)
char' _ [] = Nothing
char' c (c':s') 
  | c == c' = Just (c,s')
  | otherwise = Nothing

and it worked as expected... Why is it happening to me?

Karlenekarlens answered 11/10, 2016 at 1:1 Comment(6)
Off topic: [1] Nitpicking: Haskell Wiki /= Haskell Wikibook (it is a common mix-up). [2] If there is indeed a bug in the book it was a very appropriate moment to report it, as the MonadPlus chapter will be updated for the AMP in a short while. Thanks!Unceremonious
@Unceremonious Ok, I am going to change it to Haskell Wikibook as you saidKarlenekarlens
@Unceremonious Sorry for my ignorance, but what does AMP mean?Karlenekarlens
@Karlenekarlens Applicative-Monad ProposalOceanid
Applicative-Monad Proposal, that is, the changes in GHC 7.10 that made Applicative a superclass of Monad. To pick an arbitrary example, guard, which used to have a MonadPlus constraint, now has an Alternative one. That means there is some slightly broken code in the Monad Transformers chapter of the book (which uses guard in one example), and fixing it in the proper way will require discussing Alternative in the MonadPlus chapter.Unceremonious
(By the way, I have just fixed the code in the book.)Unceremonious
O
7

I think the wiki is wrong. They are probably confusing this with the fact that binds fail via the fail function a Monad affords. So the following example will use the fail function from Maybe, which returns Nothing:

char :: Char -> String -> Maybe (Char, String)
char c s = do
  (c':s') <- return s
  if c == c' then Just (c, s') else Nothing
Oceanid answered 11/10, 2016 at 1:15 Comment(1)
Yup, it is wrong indeed. Most likely the author of the exercise mistyped let instead of <-, and in the intervening eight years it slipped through the fingers of everyone (myself included!).Unceremonious

© 2022 - 2024 — McMap. All rights reserved.