一个人如何严格地折叠一个单子(monad)? Data.Foldable
有严格的foldl'
和单子(monad)foldlM
, 但没有严格的 foldlM'
?单子(monad)本身是否以某种方式定义了严格性?如果是这样,如何确定它是什么?
想象一下,我必须确定一个庞大的环元素列表的乘积是否为零,但我的环不是一个整数域,即它包含零除数。在这种情况下,我应该递归地拖尾 foldl
我的乘法***
在列表中,但返回 False
产品变为零的那一刻,而不是等待完整的产品。
safelist :: [p] -> Bool
safelist [] = True
safelist (x:xs) = snd $ foldl' f (x,True) xs
where f (u,b) v = (w, b && w /= Zero) where w = u *** v
我或许可以使用
Maybe
稍微简化此代码monad 的 foldlM
但这样做似乎缺乏所需的严格性。
最佳答案
没有这样的标准函数,但很容易定义:
foldM' :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
foldM' _ z [] = return z
foldM' f z (x:xs) = do
z' <- f z x
z' `seq` foldM' f z' xs
这只是标准
foldM
,但使用相同的 seq
在里面说foldl'
确实(与 foldl
相比)。它可能没有在任何标准中定义,因为它不太可能很有用:对于大多数 monad,(>>=)
在您需要使用左折叠而不溢出堆栈的意义上是“严格的”;这仅在返回值本身包含过多的 thunk 时才有用,但是 foldM
的有用应用将使用最后一步的值执行一些单子(monad)计算,这不太可能。我认为您的代码很简单;我怀疑
foldM'
会让它更优雅。
关于haskell - Haskell 有 foldlM' 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8919026/