Haskell — странное поведение блока do

Читая Викикнигу по Haskell о MonadPlus, я обнаружил следующее. функция, которая в основном принимает Char и String и возвращает Just (char,tail), если такой символ равен заголовку строки, или Nothing в противном случае:

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

и они объясняют, что let (c':s') = s не вызовет исключения, потому что он находится в блоке do, который будет оцениваться как Nothing, когда шаблон терпит неудачу, но это не так, потому что когда я попробовал это:

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

Поэтому мне пришлось переписать его на:

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

и это сработало, как и ожидалось... Почему это происходит со мной?


person FtheBuilder    schedule 11.10.2016    source источник
comment
Не по теме: [1] Придирки: Haskell Wiki /= Haskell Wikibook (обычная путаница). [2] Если в книге действительно есть ошибка, это был очень подходящий момент, чтобы сообщить о ней, так как глава MonadPlus будет обновлена ​​для AMP в ближайшее время. Спасибо!   -  person duplode    schedule 11.10.2016
comment
@duplode Хорошо, я собираюсь изменить его на Haskell Wikibook, как вы сказали.   -  person FtheBuilder    schedule 11.10.2016
comment
@duplode Извините за мое невежество, но что означает AMP?   -  person FtheBuilder    schedule 11.10.2016
comment
@FtheBuilder Предложение Applicative-Monad   -  person Alec    schedule 11.10.2016
comment
Applicative-Monad Proposal, то есть изменения в GHC 7.10, которые сделали Applicative надклассом Monad. Возьмем произвольный пример: guard, который раньше имел ограничение MonadPlus, теперь имеет ограничение Alternative. Это означает, что в главе книги, посвященной Monad Transformers, имеется некоторый слегка поврежденный код (который использует guard в одном примере), и для его правильного исправления потребуется обсуждение Alternative в главе MonadPlus.   -  person duplode    schedule 11.10.2016
comment
(Кстати, я только что исправил код в книге.)   -  person duplode    schedule 11.10.2016


Ответы (1)


Я думаю, что вики ошибается. Вероятно, они путают это с тем фактом, что связывания завершаются ошибкой через fail функция, которую предоставляет Monad. Таким образом, в следующем примере будет использоваться функция fail из Maybe, которая возвращает Nothing:

char :: Char -> String -> Maybe (Char, String)
char c s = do
  (c':s') <- return s
  if c == c' then Just (c, s') else Nothing
person Alec    schedule 11.10.2016
comment
Да, это действительно неправильно. Скорее всего, автор упражнения опечатался let вместо <-, и за прошедшие восемь лет оно ускользнуло у всех (в том числе и у меня!). - person duplode; 11.10.2016