3

I'm new to Haskell and playing around trying to understand a few things. If I do the following I receive a problem:

list1 = [1..]
list2 = [x | x <- list1, x <= 4]
print list2

which returns [1,2,3,4. There isn't an end bracket on it, so it is as if the list is loading or frozen. Here is how it looks:

Prelude> print list2
[1,2,3,4

What is going on here?

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
TheStrangeQuark
  • 2,257
  • 5
  • 31
  • 58
  • 7
    Pretend you're GHCI. Your user gives you an infinite list and asks you to find all the values in that list that are less than or equal to 4. How would you go about doing it? (Keep in mind that you don't know that the list is in order.) – user2297560 Feb 23 '17 at 13:44
  • 1
    Ahh, yeah that makes sense. Is there a way to deal with infinite lists and conditions like this? – TheStrangeQuark Feb 23 '17 at 14:12
  • 1
    You can `take 4` elements from `list1` (literally `list2 = take 4 list1`) – user28434'mstep Feb 23 '17 at 14:15

3 Answers3

7

You know that the list is monotonically increasing, but Haskell does not. Use takeWhile, instead of a list comprehension, so that list1 can stop being evaluated once you find a value greater than 4.

> list1 = [1..]
> list2 = takeWhile (<= 4) list1
> print list2
[1,2,3,4]
chepner
  • 497,756
  • 71
  • 530
  • 681
4

What happens is that list1 is still being computed, and for each new element of the list1 predicate x <= 4 is applied, which is false for every x after 4.

So, in summary:

To printout list2 interpreter need to compute list1 and check each list item that it is <= 4, and because list1 is infinite computation of it must take infinite time.

user28434'mstep
  • 6,290
  • 2
  • 20
  • 35
2

You are taking every element in list1 and, for each one that's less than 4, making it a entry in list2. Look how many elements you have in list1.

cjs
  • 25,752
  • 9
  • 89
  • 101