我将通过以下论文: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
该函数无法键入检查,错误对我来说似乎很明显。然而,作者明确指出这将有效:
... Var的情况不再需要一个fromJust调用了:原因是Map.lookup被定义为只需调用monad的失败函数就可以在任何monad中工作 - 这非常适合我们的monadic公式。
Map.lookup的签名看起来不像是用于任何monad:
lookup :: Ord k => k -> Map k a -> Maybe a
这篇论文是否已过时或者我遗失了什么?如果论文实际上已经过时,为什么lookup
改为仅与Maybe
合作。
谢谢!
你的教程来自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
。