Reverse range implementation

时间:2015-07-31 19:22:07

标签: haskell

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

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

and not

[10..1] -- yields []

It seems simple enough to implement it like this:

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

What am I not understanding here?

2 个答案:

答案 0 :(得分:10)

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

[10..1] desugars to enumFromTo

[10,9..1] desugars to enumFromThenTo

Observe how the 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, as lists generated this way can no longer always be assumed to be in ascending order. Hence the necessity to make your descending intention explicit with [x,(pred x)..y] or enumFromThenTo.

答案 1 :(得分:6)

几乎总是当你有一个像[1..n]这样的表达式,并且n恰好是0时,你想要的值是[]而不是[1,0]。例如,考虑

factorial n = product [1..n]

然后我们想要

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

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

这就是为什么[m..n]m > n时不会产生降序列表的原因。

(如果m >= n+2(例如,如果在[1..n]中,n为否定)那么它很可能是一个错误条件,可以说[m..n]应该是错误;但它仍然由语言标准定义为[]。)