Haskell maps returning a monad

谁说胖子不能爱 提交于 2019-12-05 01:22:40

Don's lift converts Maybe's elements to their general Monad counterparts, so perhaps it should be named convert or generalize or something;-)

If you just want to use lookup mainly in list comprehensions and other monads that implement a fail, you could also make use of the mapping of pattern match failure to 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"

the latter would make it much more general and allow lookup to be used in list comprehensions

The latter is also more unsafe, as the majority of monad classes define fail as error. That is, the common case of not finding an element in the Map is a program-terminating error for most monads. That, coupled with the increased likelihood of the wrong type context being inferred, means we tend to discourage the 'monadic fail return' style now.

Is there any way to mimic this behavior with the newer version

Indeed there is! Simply lift Maybe a into Monad a, like so:

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

And now you can write, e.g. lift . lookup

For the specific case of the list monad, the simplest solution is to use 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"]
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!