Home > Software design >  Infinite loop with [2,2..20] in Haskell using ghci
Infinite loop with [2,2..20] in Haskell using ghci

Time:11-28

I am just staring with Haskell reading the http://learnyouahaskell.com book. In the Texas Ranges section the author shows code for specifying a step in a range with this syntax [x,y..z] and I did that with the example, [2,4..20] and it runs smoothly, but when I run [2,2..20] I get an infinite list of 2s instead of [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]. If I run [2,3..20] I get the desired output so what I'm assuming is that there's some sort of issue with the first value of the list being 2 and I would like a more technical response on exactly why that's not allowed.Picture of console

CodePudding user response:

but when I run [2,2..20] I get an infinite list of 2s

That is expected behavior. Indeed, for a range [x, y .. z], the first number x determines the start value, the difference between y and x determines the step, and z determines the upperbound. Since the step size is 0, it will keep yielding 2s, and never produces a value greater than the upperbound 20.

If you write [e1, e2 .. e3], this is translated into enumFromThenTo e1 e2 e3 and as the Haskell report §6.3.4 says:

The sequence enumFromThenTo e1 e2 e3 is the list [e1,e1 i,e1 2i,…e3], where the increment, i, is e2 - e1. If the increment is positive or zero, the list terminates when the next element would be greater than e3; the list is empty if e1 > e3. If the increment is negative, the list terminates when the next element would be less than e3; the list is empty if e1 < e3.

CodePudding user response:

[2,4..10] is [2, 4, 6, 8, 10]

[2,3..10] is [2, 3, 4, 5, 6, 7, 8, 9, 10]

Can you see the pattern? Haskell range syntax is designed to look a bit like you might write it in plain language; just enough of the start of the list to establish a pattern, then .. to skim over intermediate elements that just continue the pattern, then the final element to know where to stop.

It is not [start, step .. stop]1; rather it is [first, second .. final].

So with that in mind, looking at [2, 2 .. 20] it's clear that this is a list that starts with 2, and then 2 is followed by 2, and then we're supposed to go on from there. But if the rule is that 2 follows 2, then generalising that we just have an infinite list of 2s (we'll stop when we get to 20, but we never get to 20).

Willem Van Onsem's answer excellently gives the exact technical definition, including the spec reference. But this is the motivation for it.


1 It would be really weird if it was, in my opinion. It's true, other languages often fill this need by providing a function of start, stop, and step in their standard library2, but they usually do it with a function; something like range(start, stop, step=1). [start, step .. stop] would be very confusing as special purpose syntax to do that with. Haskell's [first, second .. final] only exists to look like a "natural" way to write the range rather than a function call. If it didn't look kinda like natural notation we would just have a function.

2 Although maybe that's not even what you thought was going on, since you apparently got what you expected from [2, 2 .. 20] with [2, 3 .. 20], but that is start = 2, step = 1, stop = 20. So apologies if I have misconceived what your misconception is!

  • Related