8

我最近在使用threepenny-gui时遇到了一个错误 ,它通过将代码从do表示法中的<-模式匹配更改为使用let表示法的模式匹配来解决。

在这两种形式的模式匹配之间进行更改时,我是否应该期望行为发生变化?

具体如下代码:

在 IO 单子中:

Just events <- Map.lookup elid <$> readMVar sElementEvents

改为:

mevents <- Map.lookup elid <$> readMVar sElementEvents
let Just events = mevents

这是为我解决问题的提交的链接: https ://github.com/Davorak/threepenny-gui/commit/fbf6cbe25875fafdc64f7a111ddebf485b45143b

其他平台详细信息:操作系统:10.8.5 ghc:7.6.3

编辑:添加了 IO monad 正在发生这种情况的事实

4

1 回答 1

11

实际上,是的,它们会产生不同类型的错误。绑定中缺少模式匹配会在评估匹配时let引发模式匹配,而仅调用实例的函数时缺少模式匹配error(<-)Monadfail

作为一个简单的例子,考虑Maybemonad

instance Monad Maybe where
  ...
  fail _ = Nothing

test1 :: Maybe (Maybe ())
test1 = do
  Just a <- return Nothing
  return a

test2 :: Maybe (Maybe ())
test2 = do
  ma <- return Nothing
  let Just a = ma
  return a

如果我们同时调用它们,我们会得到截然不同的行为

> test1
Nothing

> test2
Just *** Exception: PM.hs:23:7-17: 
Irrefutable pattern failed for pattern Data.Maybe.Just a

一般来说,无可辩驳的匹配是一个坏主意,除非你真的确定不可能得到缺失的模式,但如果你必须在 a 中进行,Monad那么有时在绑定上无可辩驳的匹配比在 a 中更好let

于 2013-11-17T03:21:03.817 回答