I am wondering exactly how list-comprehensions are evaluated in Haskell. After reading this Removing syntactic sugar: List comprehension in Haskell and this: Haskell Lazy Evaluation and Reuse I still don't really understand if
[<function> x|x <- <someList>, <somePredicate>]
is actually exactly equivalent (not just in outcome but in evaluation) to
filter (<somePredicate>) . map (<function>) $ <someList>
and if so, does this mean it can potentially reduce time complexity drastically to build up the desired list with only desired elements? Also, how does this work in terms of infinite lists? To be specific: I assume something like:
[x|x <- [1..], x < 20]
will be evaluated in finite time, but how "obvious" does the fact that there are no more elements above some value which satisfy the predicate need to be, for the compiler to consider it? Would
[x|x <- [1..], (sum.map factorial $ digits x) == x]
work (see project Euler problem 34 https://projecteuler.net/problem=34). There is obviously an upper bound because from some x on x*9! < 10^n -1 always holds, but do I need to supply that bound or will the compiler find it?
[x|x <- [1..], x < 20]
would not terminate so I don't know what you mean by how it 'will be just fine'. No attempt to reason about the predicate is done at all. – Lee[x | x <- [1..], x < 20]
safely, and after that an attempt to find another element matching the predicate never terminates. – 9000guard
function), not a composition offilter
andmap
. – chepnerfilter (< finiteNumber) ([1..] ++ [1])
should give a list of length finiteNumber, however I understand now that it will not. Thank you guys. – Chris