List comprehensions can introduce local bindings for variables to hold some interim values:
[(x,y) | x <- [1..4], let y=x*x+1, even y] -- [(1,2),(3,10)]
Same effect can be achieved with a trick,
[(x,y) | x <- [1..4], y <- [x*x+1], even y] -- [(1,2),(3,10)]
The let
in list comprehensions is recursive, as usual. But generator bindings are not, which enables shadowing:
[x | x <- [1..4], x <- [x*x+1], even x] -- [2,10]