正在阅读haskell wiki一书的monadplus章节:https://en.wikibooks.org/wiki/Haskell/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“do-block确保任何失败的模式匹配都将导致不返回任何内容。”
然而,当我尝试digit 1 ""时,它产生了无可辩驳的运行时错误,而不是“什么都没有”。
我可以使用(c:_) <- return s来解决这个问题。如果在haskell方面更有经验的人能证实/澄清这一点,那就太好了。
发布于 2016-09-04 08:32:33
wikibooks中的代码没有考虑到输入字符串为空的情况。当执行行let (c:_) = s且s为空时,将导致模式匹配失败,并抛出异常。您的建议(c:_) <- return s实际上与所使用的非常相似,除了一个区别;当一元绑定(即<-)中的模式匹配失败时,将调用monad的fail方法。现在,在Maybe monad中,fail是defined,总是返回Nothing,所以它将导致整个do块返回Nothing。我不喜欢使用您的建议的一件事是,我个人认为使用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 = Nothinghttps://stackoverflow.com/questions/39312440
复制相似问题