Haskell映射返回monad

时间:2010-06-13 01:44:58

标签: haskell map monads maybe

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

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

3 个答案:

答案 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 liftMaybe个元素转换为其通用Monad对应元素,因此可能应将其命名为convertgeneralize或其他内容;-)

如果您只想在列表推导和其他实现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"]