12

Data.Map 和 Data.IntMap 中的查找函数当前返回带有类型签名的 Maybe 包装的值

lookup  :: Ord  k => k -> Map  k a -> Maybe  a

它曾经有更一般的类型

lookup  :: (Monad  m, Ord  k) => k -> Map  k a -> m a

我意识到前者可能会减少对额外类型规范的需求,但后者会使其更加通用并允许在列表推导中使用查找。有什么方法可以用新版本模仿这种行为,还是我必须使用旧版本的库?

4

3 回答 3

21

后者会使它更通用,并允许在列表推导中使用查找

后者也更不安全,因为大多数 monad 类将 fail 定义为error. 也就是说,在 Map 中找不到元素的常见情况是大多数 monad 的程序终止错误。再加上推断错误类型上下文的可能性增加,意味着我们现在倾向于不鼓励“monadic fail return”风格。

有没有办法用较新的版本来模仿这种行为

确实有!只需将 Maybe a 提升到 Monad a 中,如下所示:

lift :: Monad m => Maybe a -> m a
lift Nothing  = fail "you die now"
lift (Just a) = return a

现在你可以写了,例如lift . lookup

于 2010-06-13T01:52:10.057 回答
6

DonliftMaybe's 元素转换为它们的一般Monad对应元素,所以也许它应该被命名convertgeneralize其他东西;-)

如果您只想lookup主要在列表推导和其他实现 a 的 monad 中使用fail,您还可以使用模式匹配失败到的映射fail

前奏> [ v | 只需 v <- return $lookup "hi" [("ho","silver")] ]
[]
前奏> [ v | 只需 v <- 返回 $ 查找 "ho" [("ho","silver")] ]
[“银”]

Prelude> do Just v <- return $lookup "hi" [("ho","silver")] ; 打印 v
*** 例外:用户错误(<interactive>:1:3-8 处的 do 表达式中的模式匹配失败)
Prelude> do Just v <- return $lookup "ho" [("ho","silver")] ; 打印 v
“银”
于 2010-06-13T08:42:07.143 回答
5

对于 list monad 的特定情况,最简单的解决方案是使用maybeToList

Prelude> :m +Data.Maybe -- Note: Use "import Data.Maybe" in a program file

Data.Maybe> [ v | v <- maybeToList $ lookup "hi" [("ho","silver")] ]
[]
Data.Maybe> [ v | v <- maybeToList $ lookup "ho" [("ho","silver")] ]
["silver"]
于 2010-06-13T10:37:21.463 回答