I have encountered the following pattern while programming in Haskell (but the pattern could occur in any language supporting lists, option types, and mapping of a function over a list). I have types a and b and a function
f :: a -> Maybe b
Now I want to define a function that maps f on a list of type [a], but I am not interested to have a result of type [Maybe b]. Rather, I want to have Just [y1, ..., yn], if [f(x1), ..., f(xn)] == [Just y1, ..., Just yn], and Nothing otherwise (i.e. if f(xi) == Nothing for at least one i). So the result must be of type Maybe [b].
I solved this by using the following helper function:
combine :: Maybe b -> Maybe [b] -> Maybe [b]
combine me ml = do
l <- ml
e <- me
Just (e : l)
and then
g :: (a -> Maybe b) -> [a] -> Maybe [b]
g f xs = foldr combine (Just []) (map f xs)
So, for example, if I have
f x = if x > 0 then Just x else Nothing
xs0 = [1, 2, 3, 4]
xs1 = [-1, -2, 3, 4]
xs2 = [-1, -2, -3, -4]
then
map f xs0 = [Just 1, Just 2, Just 3, Just 4]
g f xs0 = Just [1, 2, 3, 4]
map f xs1 = [Nothing, Nothing, Just 3, Just 4]
g f xs1 = Nothing
map f xs2 = [Nothing, Nothing, Nothing, Nothing]
g f xs2 = Nothing
The solution with combine and foldr works, but I wanted to ask if you know of a more compact solution for turning a [Maybe a] into a Maybe [a] as described above.