Jef*_*ges 9 monads haskell fold
如何严格折叠monad? Data.Foldable
有严格foldl'
和一元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
Run Code Online (Sandbox Code Playgroud)
我也许可以使用Maybe
monad来略微简化这段代码,foldlM
但这样做看似缺乏必要的严格性.
ehi*_*ird 10
没有这样的标准功能,但很容易定义:
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
Run Code Online (Sandbox Code Playgroud)
这只是标准foldM
,但与之相同seq
(与之foldl'
相比foldl
).它可能没有在任何标准中定义,因为它不太可能是有用的:对于大多数monad来说,(>>=)
在某种意义上你需要使用左折叠而不会溢出堆栈是"严格的"; 这只有当你的过多的thunk在返回的值本身时才有用,但是一个有用的应用程序foldM
将使用最后一步的值执行一些monadic计算,这使得这不太可能.
我认为你的代码很简单; 我怀疑foldM'
会不会更优雅.