为了学习Haskell,我遇到了一种情况,我希望在列表中进行折叠,但我的累加器是一个Maybe.然而,我正在折叠的函数接受了Maybe中的"提取"值,如果一个失败,它们都会失败.我有一个解决方案,我发现kludgy,但我知道像我一样小Haskell,我相信应该有一个更好的方法.假设我们有以下玩具问题:我们想要列出一个列表,但由于某种原因四肢是坏的,所以如果我们在任何时候尝试总计四个,我们想要返回Nothing.我目前的解决方案如下:
import Maybe
explodingFourSum :: [Int] -> Maybe Int
explodingFourSum numberList =
foldl explodingFourMonAdd (Just 0) numberList
where explodingFourMonAdd =
(\x y -> if isNothing x
then Nothing
else explodingFourAdd (fromJust x) y)
explodingFourAdd :: Int -> Int -> Maybe Int
explodingFourAdd _ 4 = Nothing
explodingFourAdd x y = Just(x + y)
Run Code Online (Sandbox Code Playgroud)
所以基本上,有没有办法在explodingFourMonAdd使用某种Monad折叠时清理或消除lambda ?或者以某种方式在>> =运算符中进行曲线处理,以便折叠表现得像>> =的链接函数列表?
hug*_*omg 23
我想你可以使用foldM
explodingFourSum numberList = foldM explodingFourAdd 0 numberList
Run Code Online (Sandbox Code Playgroud)
这可以让你摆脱额外的lambda 和开始时的那个(Just 0).
顺便说一句,看看hoogle搜索你真的不记得名字的功能.
所以基本上,有没有办法使用某种单子折叠清理,或消除,在explodingFourMonAdd拉姆达?
亚普.在Control.Monad中有这个foldM功能,这正是你想要的.所以,你可以更换您的来电foldl与foldM explodingFourAdd 0 numberList.
你可以利用这个事实,即Maybemonad.该函数sequence :: [m a] -> m [a]具有以下效果,如果m是Maybe:如果列表中的所有元素都是Just x某些元素x,则结果是所有这些元素的列表.否则,结果是Nothing.
因此,您首先要确定所有元素,不管它是否失败.例如,举个例子:
foursToNothing :: [Int] -> [Maybe Int]
foursToNothing = map go where
go 4 = Nothing
go x = Just x
Run Code Online (Sandbox Code Playgroud)
然后你运行序列和fmap折叠:
explodingFourSum = fmap (foldl' (+) 0) . sequence . foursToNothing
Run Code Online (Sandbox Code Playgroud)
当然,您必须根据具体情况进行调整.
| 归档时间: |
|
| 查看次数: |
6652 次 |
| 最近记录: |