Idiomatic way to sum a list of Maybe Int in haskell

后端 未结 5 2054
粉色の甜心
粉色の甜心 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条回答
  • 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
    
    0 讨论(0)
  • 2021-02-07 07:44

    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
    
    0 讨论(0)
  • 2021-02-07 07:45
    import Data.Maybe
    import Data.List
    sumMaybes = sum . catMaybes
    
    0 讨论(0)
  • 2021-02-07 07:49

    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
    
    0 讨论(0)
  • 2021-02-07 07:55

    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.

    0 讨论(0)
提交回复
热议问题