5

I would like to have a function with the type:

f :: [Maybe a] -> Maybe [a]

e.g.

f [Just 3, Just 5] == Just [3, 5]
f [Just 3, Nothing] == Nothing
f [] == Just []

It is similar to catMaybes :: [Maybe a] -> [a] in Data.Maybe, except that catMaybes ignores Nothing, while my f is very serious about Nothing. I could implement f in a naive way (as shown below), but wondering if there is more idiomatic way (like "applicative functor"):

f :: [Maybe a] -> Maybe [a]
f xs = let ys = catMaybes xs
        in if length ys == length xs 
           then Just ys
           else Nothing

or

f :: [Maybe a] -> Maybe [a]
f xs = if all isJust xs
        then catMaybes xs
        else Nothing
Causality
  • 1,123
  • 1
  • 16
  • 28
  • 6
    As an aside heuristic -- if you're writing a typical list function, and you find yourself using `length` (especially if you use it more than once), you're probably doing something wrong. It's not suited to most list code in Haskell. That isn't always the case, but as you're learning, you should err on the side of not using it. :-) – shachaf Aug 02 '13 at 00:32
  • 4
    When in doubt, [hoogle](http://www.haskell.org/hoogle/?hoogle=%5BMaybe+a%5D+-%3E+Maybe+%5Ba%5D). I searched `[Maybe a] -> Maybe [a]` in Hoogle and got the correct answer listed below (`sequence`). – aaronlevin Aug 02 '13 at 00:42
  • 1
    I `hoogle`d it and noticed `catMaybes`. `sequence` was the first on the list. I ignored it because the type was not `Maybe` but `Monad`, and I failed to recognize the connection. – Causality Aug 02 '13 at 00:57

2 Answers2

21

The function you're searching for is called sequence:

sequence :: (Monad m) => [m a] -> m [a]

You can find this function using hoogle: link.

Example:

>>> sequence [Just 3, Just 5]
Just [3,5]

>>> sequence [] :: Maybe [Int]
Just []

Note: There is also sequenceA in Data.Traversable which is a bit generalized, but for your use case sequence from Control.Monad is enough.

Uli Köhler
  • 13,012
  • 16
  • 70
  • 120
bennofs
  • 11,873
  • 1
  • 38
  • 62
7

You want sequence from Control.Monad.

(This is also generalized in a useful way in Data.Traversable.)

shachaf
  • 8,890
  • 1
  • 33
  • 51