Sign in to follow this  
TheUnbeliever

Haskell list comprehension question

Recommended Posts

TheUnbeliever    963
I often want to do something by generating an infinite list where each element is always greater than or equal to the previous, and then generating a finite list from this. However, doing something like (yes, this particular case is a stupid example, but the principle is there):
naturals = [1..]
naturalslessthan1000 = [x | x <- naturals, x < 1000]
Is there some way of stopping the second list comprehension at the first element where the condition x < 1000 fails? This means that, for example, I can then do foldr (+) 0 naturalslessthan1000.

Share this post


Link to post
Share on other sites
Luctus    584
A list comprehension will always evaluate every item in the list. Your specific example can easily be solved though:

naturalslessthan1000 = takeWhile (<1000) naturals

Oh, and using the sum function rather than foldr (+) 0 is much more readable.

Share this post


Link to post
Share on other sites
TheUnbeliever    963
Quote:
Original post by Luctus
A list comprehension will always evaluate every item in the list. Your specific example can easily be solved though:

naturalslessthan1000 = takeWhile (<1000) naturals


takeWhile will solve the cases that I'm thinking of, thanks.

Quote:
Oh, and using the sum function rather than foldr (+) 0 is much more readable.


Great, thanks. I'm still familiarising myself with the Prelude.

Share this post


Link to post
Share on other sites
Luctus    584
Quote:
Original post by Luctus
A list comprehension will always evaluate every item in the list
I realized I formulated myself poorly here though as list comprehensions are indeed evaluated lazily. To be more correct: A list comprehension will always evaluate at least as many elements as the function consuming the list comprehension needs.

So for example take 1000 [x | x <- naturals] will evaluate 1000 elements from naturals, while take 1000 [x | x <- naturals, even x] will evaluate 2000 elements.

Share this post


Link to post
Share on other sites
TheUnbeliever    963
I realised what you meant. :-)

My previous hackish workaround had relied on this -- I'd print (in the interpreter) the full extent of the list, wait until it hung, kill it, and then return to take just as many as had worked. I think you can understand why I thought that there had to be a better way!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this