Folds might be easy to grasp visually:
foldr g z [a,b,c...,x] === g a (g b (g c (g ... (g x z) ... )))
So if g p r
doesn't use its 2nd arg, it won't force any further list access. Like you said, because of the short-circuit behaviour of ||
("logical or").
And foldl g z [a,b,c...,x] === (g ... (g (g (g z a) b) c) ... x)
.
To read the function, first we notice that the fold is applied to a list of primes, [2,3,5,7,11,13,17..]
. So it can be read as
isPrime n = n > 1 &&
foldr (\p r -> p*p > n || ((n `rem` p) /= 0 && r)) True primes
===
isPrime n = n > 1 &&
(2*2 > n || (rem n 2 /= 0 &&
(3*3 > n || (rem n 3 /= 0 &&
(5*5 > n || (rem n 5 /= 0 &&
-- the expansion stops when p*p > n
-- because (True || r) === True
......................... &&
(True) ... ))))))
In foldr
's combining function, the second argument is for "result" of folding the rest of the list; r
is a suggestive name to that effect.