Data.Map和Data.IntMap中的查找函数当前返回包含在Maybe with中的值 类型签名
lookup :: Ord k => k -> Map k a -> Maybe a
它曾经有更通用的
类型lookup :: (Monad m, Ord k) => k -> Map k a -> m a
我意识到前者可能会减少额外类型规范的需要,但后者会使它更加通用,并允许在列表推导中使用查找。有没有办法模仿新版本的这种行为,还是我必须使用旧版本的库?
答案 0 :(得分:19)
后者会使它更加通用,并允许在列表推导中使用查找
后者也更不安全,因为大多数monad类定义失败为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
答案 1 :(得分:5)
Don lift
将Maybe
个元素转换为其通用Monad
对应元素,因此可能应将其命名为convert
或generalize
或其他内容;-)
如果您只想在列表推导和其他实现lookup
的monad中使用fail
,您还可以使用模式匹配失败到fail
的映射:< / p>
Prelude> [ v | Just v <- return $ lookup "hi" [("ho","silver")] ] [] Prelude> [ v | Just v <- return $ lookup "ho" [("ho","silver")] ] ["silver"] Prelude> do Just v <- return $ lookup "hi" [("ho","silver")] ; print v *** Exception: user error (Pattern match failure in do expression at <interactive>:1:3-8) Prelude> do Just v <- return $ lookup "ho" [("ho","silver")] ; print v "silver"
答案 2 :(得分:4)
对于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"]