Haskell映射返回monad

sab*_*uma 10 monads haskell map maybe

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

lookup  :: Ord  k => k -> Map  k a -> Maybe  a
Run Code Online (Sandbox Code Playgroud)

它曾经有更普遍的类型

lookup  :: (Monad  m, Ord  k) => k -> Map  k a -> m a
Run Code Online (Sandbox Code Playgroud)

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

Don*_*art 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
Run Code Online (Sandbox Code Playgroud)

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


cla*_*aus 5

唐的lift转换Maybe的元素,其一般Monad的同行,所以也许它应该被命名convert或者generalize什么;-)

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

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"


Yit*_*itz 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"]
Run Code Online (Sandbox Code Playgroud)