I was looking for a creation foldlthat works in endless lists, for situations where you could not get guarded recursion, but where, depending on the first argument, the second argument cannot be used.
For example, multiplication, where you usually need both arguments and protected recursion, does not work, but if the first argument is 0, you can short circuit.
So, I wrote the following function:
foldlp :: (b -> a -> b) -> (b -> Bool) -> b -> [a] -> b
foldlp f p = go where
go b [] = b
go b (x : xs)
| p b = go (f b x) xs
| otherwise = b
And tested it with my short circuit function:
mult :: Integer -> Integer -> Integer
mult 0 _ = 0
mult x y = x * y
main :: IO ()
main = print . <test_function>
The results obtained using -prof -fprof-auto -O2, +RTS -pwere as follows:
foldlp mult (/= 0) 1 $ replicate (10 ^ 7) 1
total time = 0.40 secs
total alloc = 480,049,336 bytes
foldlp mult (`seq` True) 1 $ replicate (10 ^ 7) 1
total time = 0.37 secs
total alloc = 480,049,336 bytes
foldl' mult 1 $ replicate (10 ^ 7) 1
total time = 0.37 secs
total alloc = 480,049,352 bytes
foldl mult 1 $ replicate (10 ^ 7) 1
total time = 0.74 secs
total alloc = 880,049,352 bytes
foldr mult 1 $ replicate (10 ^ 7) 1
total time = 0.87 secs
total alloc = 880,049,336 bytes
This was very promising, as my custom function allows flexible types of stringency, and also works with infinite lists.
, 0, foldr, foldr .
, thunks , ((1 + 2) + 3, (10 + 20) + 30) WHNF, foldl'.
foldl flip foldl (const True) foldl' flip foldl ( seq True). , -, .
, , , foldlp Foldable.
, , {-# INLINE foldlp #-}, , :
foldlp mult (/= 0) 1 $ replicate (10 ^ 7) 1
total time = 0.67 secs
total alloc = 800,049,336 bytes
, - . , , .