It's actually pretty elegant.
First, we define a function sieve that takes a list of elements:
sieve (p:xs)
In the body of sieve, we take the head of the list (because we're passing the infinite list [2..], and 2 is defined to be prime) and append it to the result of applying sieve to the rest of the list:
p : sieve (filter (\ x -> x 'mod' p /= 0) xs)
So let's look at the code that does the work on the rest of the list:
sieve (filter (\ x -> x 'mod' p /= 0) xs)
We're applying sieve to a filtered list. Let's break down what the filter part does:
filter (\ x -> x 'mod' p /= 0) xs
filter takes a function and a list on which we apply that function, and retains elements that meet the criteria given by the function. In this case, filter takes an anonymous function:
\ x -> x 'mod' p /= 0
This anonymous function takes one argument, x. It checks the modulus of x against p (the head of the list, every time sieve is called):
x 'mod' p
If the modulus is not equal to 0:
'mod' p /= 0
Then the element x is kept in the list. If it is equal to 0, it's filtered out. This makes sense: if x is divisible by p, than x is divisible by more than just 1 and itself, and thus it is not prime.