I am a newbie to Haskell programming and have trouble understanding how the below list comprehension expands.
primes = sieve [2..]
sieve (p:xs) = p : sieve [x | x <-xs, x `mod` p /= 0]
Can someone correct me how the sieve
expansion works:
- As we are pattern matching in
sieve
,p
would associate to2
andx
s from[3..]
. - Next, in the list comprehension
x<-3
, but then how can we call sieve with just3
when there is no short-circuit.
Other thing I do not understand is how recursion works here.
I think it would be clear if one could expand the above one step at a time for first few numbers, say until 5
.
Here is an operational description of what
sieve
does.To compute
sieve (x:xs)
:x
.xs
, letys
be the listxs
with all of the multiples ofx
removed.sieve
onys
defined in step 2.Here is how the first couple of terms are computed:
and then:
and then:
etc.
Using an auxiliary function
we can rewrite the
sieve
function asIn imperative pseudocode, we could write it as
This pattern of repeated applications is known as iteration:
So that
Naturally, head element of each transformed sequence on each step will be a prime, since we've removed all the multiples of the preceding primes on previous steps.
Haskell is lazy, so transformations won't be done in full on each step, far from it - only as much will be done as needed. That means producing only the first element, and "making a notice" to perform the transformation further when asked:
Incidentally, this should give us an idea: 3 needn't really be tested by 2; 4..8 needn't really be tested by 3, let alone 5 or 7; 9..24 shouldn't really be tested by 5; etc. What we want is the following:
i.e. we want the creation of each
>>= noMult p
filter postponed untilp*p
is reached in the input.Let's do some equational reasoning.
The
[2..]
is sintactic sugar for[2, 3, 4, 5, ...]
soInline
sieve
once:First,
x
gets value3
which passes themod 2
filterInline
sieve
again (I renamedx
toy
to prevent confusions)Now
x = 4
fails themod 2
filter butx = 5
passes it. SoThis
y = 5
also passes themod 3
filter so now we haveExpanding
sieve
one more time (z
instead ofy
) gets us toAnd the expansion continues on the same way.