mkUltra
mkUltra

Reputation: 3068

Strange result of List generation in Haskell

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

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

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 Integers 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, 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.

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

Related Questions