Is there a more idiomatic way to implement the following? I feel like I\'m missing a way to get rid of the lambda, but couldn\'t figure out a way to convert it to point-free. Ma
The most direct way to eliminate the lambda is to use liftA2
; it's exactly the code you wrote
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2 f x y = pure f <*> x <*> y
foldl (liftA2 (+)) (Just 0) [Just 1, Just 2]
then we have a few choices for how to propagate the errors. This code has it that any Nothing
will lead to a total failure. We can do that in two steps like @bhekilr suggested using sequence
.
sum <$> sequence [Just 1, Just 2] sum <$> sequence [Just 1, Nothing]
Just (sum [1,2]) sum <$> Nothing
Just 3 Nothing
We can also use the fact that (+)
induces a Monoid
on the values in order to just "ignore" Nothing
s. Most literally that would be
import Data.Monoid
getSum $ foldMap (maybe mempty Sum) [Just 1, Just 2, Nothing]
-- equivalent to, but faster than
getSum . mconcat . map (maybe mempty Sum) $ [Just 1, Just 2, Nothing]
getSum . mconcat $ [Sum 1, Sum 2, Sum 0]
3
But we can also use catMaybe
from Data.Monoid
to do it in two steps
sum . catMaybes $ [Just 1, Just 2, Nothing]
sum [1, 2]
3
You can lift the (+) in the Maybe Monad with:
input> fold (liftM2 (+)) (Just 0) [Just 1, Just 2]
Just 3
input> fold (liftM2 (+)) (Just 0) [Just 1, Just 2, Nothing]
Nothing
import Data.Maybe
import Data.List
sumMaybes = sum . catMaybes
I'd just use sequence
from Control.Monad:
> fmap sum $ sequence [Just 3, Just 4]
Just 7
> fmap sum $ sequence [Just 3, Just 4, Nothing]
Nothing
For the point-free form:
sumMaybe :: Num a => [Maybe a] -> Maybe a
sumMaybe = fmap sum . sequence
I think foldM
works well here.
import Control.Monad
sumMay = foldM (fmap . (+)) 0
I think it's the clearest as it maps (Ba duh duh ching) to what you'd do in pure code.