Haskell Map.lookup的结果可能不是使用我的Monad Transformer堆栈进行类型检查

Haskell Map.lookup的结果可能不是使用我的Monad Transformer堆栈进行类型检查,haskell,dictionary,monads,monad-transformers,maybe,Haskell,Dictionary,Monads,Monad Transformers,Maybe,我正在审阅以下论文:。在第2.1节“转换为单子样式”中,函数被转换为在Eval1monad中返回Value。这部分功能对我来说没有意义: eval1 env (Var n) = Map.lookup n env 结果将是可能值,但是函数的类型签名是: eval1 :: Env → Exp → Eval1 Value 函数无法进行类型检查,错误对我来说很明显。但作者明确表示,这将起作用: 。。。Var案例不再需要fromJust调用:原因是Map.lookup被定义为只需调用monad的fai

我正在审阅以下论文:。在第2.1节“转换为单子样式”中,函数被转换为在
Eval1
monad中返回
Value
。这部分功能对我来说没有意义:

eval1 env (Var n) = Map.lookup n env
结果将是
可能值
,但是函数的类型签名是:

eval1 :: Env → Exp → Eval1 Value
函数无法进行类型检查,错误对我来说很明显。但作者明确表示,这将起作用:

。。。Var案例不再需要fromJust调用:原因是Map.lookup被定义为只需调用monad的fail函数就可以在任何monad中工作——这非常符合我们这里的monadic公式

Map.lookup的签名看起来不像设计用于任何monad:

lookup :: Ord k => k -> Map k a -> Maybe a
这篇论文过时了还是我遗漏了什么?如果这篇论文实际上已经过时了,为什么
lookup
更改为只使用
Maybe


谢谢

您的教程是从2006年开始的。它使用的
查找
的类型实际上是:

lookup :: (Monad m, Ord k) => k -> Map k a -> m a
我认为发生这种变化是因为
fail
被广泛认为是
Monad
类中的一个缺点。返回一个
可能是一个
使得查找失败变得明确且易于管理。在我看来,将其隐藏在
fail
后面,只是为了有一个稍微方便一点的类型,从而使其隐式化是相当肮脏的(另请参见)

您可以使用此改编版本的
查找
,按照教程进行操作:

fallibleLookup :: (Ord k, Monad m) => k -> Map.Map k a -> m a
fallibleLookup k = maybe (fail "fallibleLookup: Key not found") pure . Map.lookup k

请注意,在
m
上使用的适当约束将是
MonadFail
而不是
Monad

它已过时(因为
容器
版本0.2.0.0,从2008年起)。这种方法曾一度流行,但后来又过时了。请看,特别是不要Stewart的答案。下次你想知道界面是否发生了变化时,你通常可以通过查看Hackage上的新旧版本来得到答案。