5

HaskellWiki 的Do notation 被认为是有害的,有用的应用程序部分,我发现:

值得一提的是,do 有时会承担你写无聊的事情的负担。

例如在

getRight :: Either a b -> Maybe b
getRight y =
   do Right x <- y
      return x

a caseon y 包括在内,如果 y 不是 Right(即 Left),则调用失败,因此在这种情况下返回 Nothing。

对模式不匹配调用fail( Nothing) 听起来很有趣,所以我想尝试一下。但是,语法看起来是错误的——我们不在Eithermonad 中,那么我们如何从中提取任何东西y呢?

事实上,我试过了,它给了我“无法将类型 `Either a' 与 `Maybe' 匹配”。所以让我们在这里使用正确的模式匹配器let

getRight y = do { let (Right x) = y; return x }

这给了我一个语法错误“输入`}'的解析错误”。并不是说我明白为什么这不起作用,但让我们用多行表示法写出来:

getRight y = do
    let (Right x) = y
    return x

啊,这似乎有效 - 至少解析。然而:

*Main> getRight (Right 5)
Just 5
*Main> getRight (Left 5)
Just *** Exception: […]\test.hs:16:13-25: Irrefutable pattern failed for pattern (Data.Either.Right x)
-- `Nothing` was expected

是什么赋予了?所以我现在的问题是:

  • 这里发生了什么?为什么我的分号大括号行不起作用?
  • 如何正确地做到这一点(使用do,其他一切都是微不足道的)?
4

1 回答 1

9

该示例可能是

getRight :: Either a b -> Maybe b
getRight y =
   do Right x <- return y -- note: return = Just
      return x

模式匹配失败调用的地方fail = const Nothing。它被翻译成:

getRight y = let ok (Right x) = do {return x}
                 ok _         = fail "pattern mismatch error"
             in return y >>= ok

FWIW 最有经验的人似乎认为fail一种Monad方法是一种缺陷。查看MonadPlus可能更原则性的失败方法。

于 2014-02-26T22:20:50.387 回答