是否有更惯用的方式来实现以下内容?我觉得我错过了摆脱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
答案 0 :(得分:25)
我只使用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
答案 1 :(得分:14)
消除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
这一事实,以便“忽略”Nothing
。最字面意思是
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
但我们也可以使用catMaybe
中的Data.Monoid
分两步执行此操作
sum . catMaybes $ [Just 1, Just 2, Nothing]
sum [1, 2]
3
答案 2 :(得分:11)
我认为foldM
在这里效果很好。
import Control.Monad
sumMay = foldM (fmap . (+)) 0
我认为它是最清晰的,因为它映射(Ba duh duh ching)你在纯代码中所做的事情。
答案 3 :(得分:2)
您可以使用:
解除Maybe Monad中的(+)input> fold (liftM2 (+)) (Just 0) [Just 1, Just 2]
Just 3
input> fold (liftM2 (+)) (Just 0) [Just 1, Just 2, Nothing]
Nothing
答案 4 :(得分:0)
import Data.Maybe
import Data.List
sumMaybes = sum . catMaybes