Idiomatic way to sum a list of Maybe Int in haskell

后端 未结 5 2132
粉色の甜心
粉色の甜心 2021-02-07 07:04

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

5条回答
  •  不要未来只要你来
    2021-02-07 07:39

    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" Nothings. 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
    

提交回复
热议问题