Reputation: 3068
From Ranges in Haskell (GHCi) it's pretty much clear why the [2, 2..20]
generate infinity list.
The next value is the same, that why this code produces infinity list.
And looks like it doesn't care about limit because of [2, 2..2]
generate also infinity list.
Question:
Why the following code [2, 2..(-20)]
generate empty list instead?
Upvotes: 3
Views: 96
Reputation: 477240
In short: This is intended behavior.
The [x, y..z]
expression is syntactical sugar for enumFromThenTo x y z
with enumFromThenTo :: a -> a -> a -> [a]
.
For Integer
s it is implemented like:
instance Enum Integer where # ... enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim
So it will call enumDeltaToInteger 2 0 (-20)
. The enumDeltaToInteger
is implemented with [src]:
enumDeltaToInteger :: Integer -> Integer -> Integer -> [Integer] enumDeltaToInteger x delta lim | delta >= 0 = up_list x delta lim | otherwise = dn_list x delta lim
Soo it is considered to be an up_list
, and the up_list
will increase until it has reached a value larger than lim
:
up_list :: Integer -> Integer -> Integer -> [Integer] up_list x0 delta lim = go (x0 :: Integer) where go x | x > lim = [] | otherwise = x : go (x+delta)
This is how it has been described in the Haskell'10 report on the Enum
class:
The sequence
enumFromThenTo e1 e2 e3
is the list[e1,e1 + i,e1 + 2i,…e3]
, where the increment,i
, ise2 − e1
. If the increment is positive or zero, the list terminates when the next element would be greater thane3
; the list is empty ife1 > e3
. If the increment is negative, the list terminates when the next element would be less thane3
; the list is empty ife1 < e3
.
So the document says that if the "step" is zero or more, and e1 > e3
, then the result is the empty list.
It is indeed a "tricky" case however. I personally agree that using a special case for 0
as "step" would make sense (although I'm not per se saying this is more favorable than using the up_list
implementation). It is however how things are defined.
Upvotes: 2