Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell maps returning a monad

The lookup function in Data.Map and Data.IntMap currently return values wrapped in Maybe with the type signature

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

It used to have the more general type of

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

I realize the former likely reduces the need of extra type specification, but the latter would make it much more general and allow lookup to be used in list comprehensions. Is there any way to mimic this behavior with the newer version, or would I have to use an older version of the library?

like image 487
sabauma Avatar asked Jun 13 '10 01:06

sabauma


People also ask

Is map a monad?

Map is not one of the defining properties of monads, however, because it's technically just a special case of FlatMap. A lifting function like Unit will wrap its object in a container, even if that object is itself the same type of container.

What is a Haskell monad?

In Haskell a monad is represented as a type constructor (call it m ), a function that builds values of that type ( a -> m a ), and a function that combines values of that type with computations that produce values of that type to produce a new computation for values of that type ( m a -> (a -> m b) -> m b ).

Is Haskell list a monad?

Lists are a fundamental part of Haskell, and we've used them extensively before getting to this chapter. The novel insight is that the list type is a monad too! As monads, lists are used to model nondeterministic computations which may return an arbitrary number of results.

Does Haskell return?

Haskell functions can take functions as parameters and return functions as return values.


2 Answers

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

like image 88
Don Stewart Avatar answered Sep 18 '22 17:09

Don Stewart


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"]
like image 31
Yitz Avatar answered Sep 21 '22 17:09

Yitz