我将通过以下文件:Monad Transformers Step by Step。在第2.1节“转换为Monadic样式”中,函数转换为Value
monad中的Eval1
。这部分功能对我来说没有意义:
eval1 env (Var n) = Map.lookup n env
结果将是Maybe Value
,但函数的类型签名是:
eval1 :: Env → Exp → Eval1 Value
该函数未能键入check,错误对我来说似乎很明显。然而,作者明确指出这将有效:
... Var案例不再需要fromJust调用了:原因是Map.lookup被定义为只需调用monad的失败函数就可以在任何monad中工作 - 这非常适合我们的monadic表达式。
Map.lookup的签名看起来不像是用于任何monad:
lookup :: Ord k => k -> Map k a -> Maybe a
这篇论文是否已过时或我遗失了什么?如果论文实际上已过时,为什么lookup
更改为仅与Maybe
一起使用。
谢谢!
答案 0 :(得分:14)
你的教程是从2006年开始的。它使用的是a very old version of Data.Map
lookup
的类型确实是:
lookup :: (Monad m, Ord k) => k -> Map k a -> m a
我认为发生了变化,因为fail
被广泛认为是Monad
类中的疣。返回Maybe a
会使查找失败变得明确且易于管理。将它隐藏在fail
之后隐藏它只是为了让一个稍微方便的类型是非常脏的IMO。 (另见the question linked to by Ørjan。)
您可以使用此lookup
的改编版本来完成教程:
fallibleLookup :: (Ord k, Monad m) => k -> Map.Map k a -> m a
fallibleLookup k = maybe (fail "fallibleLookup: Key not found") pure . Map.lookup k
请注意,with the upcoming release of GHC 8.8 m
上使用的正确约束将是MonadFail
而不是Monad
。