It should be 2 <= k <= n-2, otherwise 4 would be prime (with the <).
Without functions, it can be written as
[n | n<-[2..], []<-[[i | i<-[2..div n 2], rem n i==0]]] -- or, even,
[n | n<-[2..], []<-[[j | i<-[2..n-2], j<-[i*i, i*i+i..n], j==n]]] -- no `i` dividing `n`
The last code snippet is remarkable for being both a trial division and a sieve of Eratosthenes working through addition only (becoming the true sieve when the computational redundancies are discovered and eliminated through rearrangement and sharing of repeated calculations).
To your question specifically, return
is out of place there. Test expressions in list comprehensions are simply expressions of type Bool
. The False
result means rejection of the currently generated value; True
means acceptance — and therefore inclusion in the list of results.
Another thing is, repeated failed testing of repeatedly generated values means infinite looping, when for all values of k
above n-2
(generated by k<-[2..]
without end) your test (k>=2) && (k<=(n-2))
will always fail (and cause the next k
being generated, and the next one, and the next...).
Instead of testing, we stop the generation after n-2
altogether, with [2..n-2]
, so the test condition always holds by construction — and were it would fail, those values of k
are not generated at all, in the first place.