首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >haskell wikibook monadplus潜在错误

haskell wikibook monadplus潜在错误
EN

Stack Overflow用户
提问于 2016-09-04 08:14:12
回答 1查看 46关注 0票数 0

正在阅读haskell wiki一书的monadplus章节:https://en.wikibooks.org/wiki/Haskell/MonadPlus

代码语言:javascript
复制
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

“do-block确保任何失败的模式匹配都将导致不返回任何内容。”

然而,当我尝试digit 1 ""时,它产生了无可辩驳的运行时错误,而不是“什么都没有”。

我可以使用(c:_) <- return s来解决这个问题。如果在haskell方面更有经验的人能证实/澄清这一点,那就太好了。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-04 08:32:33

wikibooks中的代码没有考虑到输入字符串为空的情况。当执行行let (c:_) = ss为空时,将导致模式匹配失败,并抛出异常。您的建议(c:_) <- return s实际上与所使用的非常相似,除了一个区别;当一元绑定(即<-)中的模式匹配失败时,将调用monad的fail方法。现在,在Maybe monad中,faildefined,总是返回Nothing,所以它将导致整个do块返回Nothing。我不喜欢使用您的建议的一件事是,我个人认为使用fail不是最优雅的解决方案,在这种情况下,我更喜欢使用case表达式:

代码语言:javascript
复制
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块。

最后,这里是上面代码的一个更紧凑的版本:

代码语言:javascript
复制
digit :: Int -> String -> Maybe Int
digit i s | 0 <= i, i <= 9, c:_ <- s, [c] == show i = Just i
          | otherwise = Nothing
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39312440

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档