Search code examples
haskellpattern-matchingdo-notation

Haskell - Strange do block behavior


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?


Solution

  • 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