符号与let中的模式匹配

Dav*_*rak 8 haskell pattern-matching do-notation threepenny-gui

我最近在使用threepenny-gui时遇到了一个错误 ,它通过将符号中的模式匹配的代码更改为<-与let符号的模式匹配来解决.

在这两种模式匹配形式之间进行转换时,我是否应该期望改变行为?

具体如下代码:

在IO monad中:

Just events <- Map.lookup elid <$> readMVar sElementEvents
Run Code Online (Sandbox Code Playgroud)

改为:

mevents <- Map.lookup elid <$> readMVar sElementEvents
let Just events = mevents
Run Code Online (Sandbox Code Playgroud)

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

其他平台细节:os:10.8.5 ghc:7.6.3

编辑:添加了这个发生在IO monad的事实

J. *_*son 11

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

举个简单的例子,考虑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
Run Code Online (Sandbox Code Playgroud)

如果我们同时调用它们,我们就会产生截然不同的行为

> test1
Nothing

> test2
Just *** Exception: PM.hs:23:7-17: 
Irrefutable pattern failed for pattern Data.Maybe.Just a
Run Code Online (Sandbox Code Playgroud)

一般来说无可辩驳的匹配是一个坏主意,除非你真的确定它是不可能得到缺少的模式,但如果你必须在做Monad,然后有时在绑定无可辩驳的匹配比更好let.

  • `let`绝对可以像'do {let Just x = Just(); 返回x}`相当于`return(让x中的Just x = Just())`,而绑定模式匹配相同的东西仍然需要让monad有机会执行绑定. (2认同)
  • 语义上这种奇怪的微小差异实际上是"Monad"具有"失败"功能的全部原因,因为它在"MonadPlus"之前就已存在.还有各种提议,其中`Monad`模式匹配desugar到`let`绑定或仅对`MonadPlus`的实例有效. (2认同)