【问题标题】:Idiomatic way to sum a list of Maybe Int in haskell在haskell中总结Maybe Int列表的惯用方式
【发布时间】:2013-11-17 18:52:29
【问题描述】:

有没有更惯用的方法来实现以下内容?我觉得我错过了摆脱 lambda 的方法,但无法找到将其转换为无点的方法。也许还有另一种更直接的非应用方式?

import Data.Maybe
import Control.Applicative

foldl (\x y -> pure (+) <*> x <*> y) (Just 0) [Just 3, Just 4]
-- Just 7

foldl (\x y -> pure (+) <*> x <*> y) (Just 0) [Just 3, Just 4, Nothing]
-- Nothing

【问题讨论】:

    标签: haskell


    【解决方案1】:

    我只使用 Control.Monad 中的sequence

    > fmap sum $ sequence [Just 3, Just 4]
    Just 7
    > fmap sum $ sequence [Just 3, Just 4, Nothing]
    Nothing
    

    对于无点形式:

    sumMaybe :: Num a => [Maybe a] -> Maybe a
    sumMaybe = fmap sum . sequence
    

    【讨论】:

    • 无法使用 ghci 7.6.3 进行评估,但可以使用 7.8.3
    【解决方案2】:

    消除 lambda 最直接的方法是使用liftA2;就是你写的代码

    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]
    

    那么对于如何传播错误,我们有几个选择。这段代码表明任何Nothing 都会导致完全失败。我们可以像@bhekilr 建议的使用sequence 那样分两步来做到这一点。

    sum <$> sequence [Just 1, Just 2]     sum <$> sequence [Just 1, Nothing]
    Just (sum  [1,2])                     sum <$> Nothing
    Just 3                                Nothing
    

    我们还可以使用(+) 在值上诱导Monoid 的事实,以便“忽略”Nothings。最字面意思是

    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
    

    但我们也可以使用Data.Monoid中的catMaybe分两步完成

    sum . catMaybes $ [Just 1, Just 2, Nothing]
    sum [1, 2]
    3
    

    【讨论】:

    • 另外,请注意(pure f &lt;*&gt;) ≡ (f &lt;$&gt;)(其中&lt;$&gt;fmap的中缀形式)。
    【解决方案3】:

    我认为foldM 在这里工作得很好。

    import Control.Monad
    sumMay = foldM (fmap . (+)) 0
    

    我认为这是最清晰的,因为它将(Ba duh duh ching)映射到您在纯代码中所做的事情。

    【讨论】:

      【解决方案4】:

      您可以通过以下方式解除 Maybe Monad 中的 (+):

      input> fold (liftM2 (+)) (Just 0) [Just 1, Just 2]
      Just 3
      input> fold (liftM2 (+)) (Just 0) [Just 1, Just 2, Nothing]
      Nothing
      

      【讨论】:

        【解决方案5】:
        import Data.Maybe
        import Data.List
        sumMaybes = sum . catMaybes
        

        【讨论】:

        • 这没有通过第二个例子(当any元素是Nothing时需要返回Nothing
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多