2016-09-04 2 views
0

читает MonadPlus глава Haskell вики книги: https://en.wikibooks.org/wiki/Haskell/MonadPlusHaskell wikibook MonadPlus потенциальная ошибка

digit :: Int -> String -> Maybe Int 
digit i s | i > 9 || i < 0 = Nothing 
      | otherwise  = do 
    let (c:_) = s 
    if [c] == show i then Just i else Nothing 

«сделай блок гарантирует, что любой неудачный матч шаблон приведет не возвращая ничего.»

Однако, когда я попробовал digit 1 "", он производит неопровержимую ошибку времени выполнения, вместо «Nothing».

Я могу обойти его, используя (c:_) <- return s. Было бы здорово, если бы кто-то более опытный в haskell смог подтвердить/разъяснить это.

+1

Я думаю, что это просто плохой пример анализаторов и MonadPlus. – ErikR

ответ

2

Код в wikibooks не учитывает случай, когда входная строка пуста. Когда выполняется строка let (c:_) = s, и s пуст, это приведет к сбою в сопоставлении с шаблоном, и будет выбрано исключение. Ваше предложение (c:_) <- return s на самом деле очень похоже на используемое, за исключением одной разницы; когда совпадение шаблонов в монадическом связывании (то есть <-) не выполняется, тогда будет вызываться метод монады fail. Теперь, в монаде Maybe, fail является defined, чтобы всегда возвращать Nothing, поэтому он приведет к возврату целого блока doNothing. Одна вещь, которую я не люблю об использовании предложения в том, что лично я не считаю, используя fail наиболее элегантное решение, и я предпочел бы использовать выражение case в случае:

digit :: Int -> String -> Maybe Int 
digit i s | i > 9 || i < 0 = Nothing 
      | otherwise  = 
    case s of 
     c:_ | [c] == show i -> Just i 
     _ -> Nothing 

В самом деле, как вы можете видеть, нам не нужно использовать блок do.

Наконец, вот более компактный вариант кода выше:

digit :: Int -> String -> Maybe Int 
digit i s | 0 <= i, i <= 9, c:_ <- s, [c] == show i = Just i 
      | otherwise = Nothing 
+0

Спасибо за объяснение. IOW, претензия в wikibook: «Блок do гарантирует, что любое неудачное совпадение шаблонов приведет к возврату Nothing». неверно, правильно? –

+0

@AlbertNetymk Да, вы могли бы сказать, что – redneb

Смежные вопросы