How does one fold over a monad strictly? Data.Foldable
has the strict foldl'
and the monadic foldlM
, but no strict foldlM'
? Is the strictness somehow defined by the monad itself? If so, how does one work out what it is?
Imagine I must determine whether the product of an enormous list of ring elements is zero, but my ring isn't an integral domain, i.e. it contains zero devisors. In this case, I should tail recursively foldl
my multiplication ***
over the list, but return False
the moment the product becomes zero, rather than waiting on the full product.
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
I could perhaps simplify this code slightly using the Maybe
monad's foldlM
but doing so seemingly lacks the required strictness.
There's no such standard function, but it's easy to define:
This is just the standard
foldM
, but with the sameseq
ing in it thatfoldl'
does (compared tofoldl
). It's probably not defined anywhere standard because it's not likely to be all that useful: for most monads,(>>=)
is "strict" in the sense you need to use a left-fold without overflowing the stack; this is only useful when your excessive thunks are in the returned values themselves, but a useful application offoldM
will perform some monadic computation with the value from the last step, making that unlikely.I think your code is simple enough as it is; I doubt
foldM'
would make it any more elegant.