【问题标题】:The Maybe result from Map.lookup is not type checking with my Monad Transformer stackMap.lookup 的 Maybe 结果不是使用我的 Monad Transformer 堆栈进行类型检查
【发布时间】:2015-11-01 03:12:44
【问题描述】:

我正在阅读以下论文:Monad Transformers Step by Step。在第 2.1 节“转换为 Monadic 样式”中,将一个函数转换为在 Eval1 monad 中返回 Value。这部分功能对我来说没有意义:

eval1 env (Var n) = Map.lookup n env

结果将是 Maybe Value 但是函数的类型签名是:

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 一起使用。

谢谢!

【问题讨论】:

  • 它已经过时了(自 2008 年以来 containers 版本 0.2.0.0)。这种方法一度流行,但后来又过时了。请参阅this question,尤其是 Don Stewart 的回答。
  • 下次您想知道某个界面是否发生了变化时,您通常可以通过查看 Hackage 上的新旧版本来获得答案。

标签: haskell dictionary monads monad-transformers maybe


【解决方案1】:

你的教程是 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.8m 上使用的正确约束将是MonadFail 而不是Monad

【讨论】:

    猜你喜欢
    • 2011-01-06
    • 2014-05-03
    • 1970-01-01
    • 2019-05-28
    • 1970-01-01
    • 2012-10-16
    • 2017-09-01
    • 2011-07-01
    相关资源
    最近更新 更多