Reversible range

For the record, I have a Haskell noob. I am trying to understand why a range can be declared as

[1..10] -- yields [1,2,3,4,5,6,7,8,9,10] 

but not

 [10..1] -- yields [] 

It seems simple enough to implement it as follows:

 (.:.) :: Enum a => a -> a -> [a] (.:.) ab = | a == b = [] | a > b = a : (a - 1) .:. b | a < b = a : (a + 1) .:. b 

What I don’t understand here?

+7
haskell
source share
2 answers

Try [10,9..1] instead of [10..1]

[10..1] desugars before enumFromTo

[10,9..1] desugars before enumFromThenTo

Notice how functions behave in GHCI:

 Prelude> [10..1] [] Prelude> [10,9..1] [10,9,8,7,6,5,4,3,2,1] Prelude> :t enumFromTo enumFromTo :: Enum a => a -> a -> [a] Prelude> :t enumFromThenTo enumFromThenTo :: Enum a => a -> a -> a -> [a] Prelude> enumFromTo 10 1 [] Prelude> :t enumFromThenTo 10 9 1 [10,9,8,7,6,5,4,3,2,1] 

The new behavior that you implemented in (.:.) Will rarely be a desirable default, since the lists generated in this way can no longer be considered always in ascending order. Therefore, you must make your downward intent explicit with [x,(pred x)..y] or enumFromThenTo .

+7
source share

Almost always, when you have an expression like [1..n] and n is 0, you want the value to be [] , not [1,0] . For example, consider

 factorial n = product [1..n] 

Then we want

 factorial 0 ~~> product [1..0] ~~> product [] ~~> 1 -- correct 

not

 factorial 0 ~~> product [1..0] ~~> product [1,0] ~~> 0 -- oops 

This is why [m..n] does not create a top-down list when m > n .

(If m >= n+2 (for example, if in [1..n] , n negative), then, most likely, the error condition and, possibly, [m..n] should be an error, but it still defined by the language standard be [] .)

+6
source share

All Articles