Scala offers a List#flatten method for going from List[Option[A]] to List[A].
scala> val list = List(Some(10), None)
list: List[Option[Int]] = List(Some(10), None)
scala> list.flatten
res11: List[Int] = List(10)
I attempted to implement it in Haskell:
flatten :: [Maybe a] -> [a]
flatten xs = map g $ xs >>= f
f :: Maybe a -> [Maybe a]
f x = case x of Just _ -> [x]
Nothing -> []
-- partial function!
g :: Maybe a -> a
g (Just x) = x
However I don't like the fact that g is a partial, i.e. non-total, function.
Is there a total way to write such flatten function?
Your flatten is the same as catMaybes (link) which is defined like this:
catMaybes :: [Maybe a] -> [a]
catMaybes ls = [x | Just x <- ls]
The special syntax Just x <- ls in a list comprehension means to draw an element from ls and discard it if it is not a Just. Otherwise assign x by pattern matching the value against Just x.
A slight modification of the code you have will do the trick:
flatten :: [Maybe a] -> [a]
flatten xs = xs >>= f
f :: Maybe a -> [a]
f x = case x of Just j -> [j]
Nothing -> []
If we extract the value inside of the Just constructor in f, we avoid g altogether.
Incidentally, f already exists as maybeToList and flatten is called catMaybes, both in Data.Maybe.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With