Haskell 中列表生成的奇怪结果
Strange result of List generation in Haskell
从 Ranges in Haskell (GHCi) 可以很清楚为什么 [2, 2..20]
生成无限列表。
下一个值是相同的,这就是这段代码产生无限列表的原因。
而且看起来它并不关心限制,因为 [2, 2..2]
也会生成无限列表。
问题:
为什么下面的代码 [2, 2..(-20)]
生成空列表?
简而言之:这是预期的行为。
[x, y..z]
表达式是 enumFromThenTo x y z
和 enumFromThenTo :: a -> a -> a -> [a]
的语法糖。
对于 Integer
s 它的实现方式如下:
instance Enum Integer where
# ...
enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim
所以它会调用 enumDeltaToInteger 2 0 (-20)
。 enumDeltaToInteger
is implemented with [src]:
enumDeltaToInteger :: Integer -> Integer -> Integer -> [Integer]
enumDeltaToInteger x delta lim
| <b>delta >= 0 = up_list x delta lim</b>
| otherwise = dn_list x delta lim
所以它被认为是一个up_list
,并且up_list
会增加直到它达到大于lim
的值:
up_list :: Integer -> Integer -> Integer -> [Integer]
up_list x0 delta lim = go (x0 :: Integer)
where
go x | <b>x > lim = []</b>
| otherwise = x : go (x+delta)
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
.
所以文档说如果"step"是零个或多个,并且e1 > e3
,那么结果是空列表。
不过确实是"tricky"的情况。我个人同意使用 0
作为 "step" 的特例是有意义的(尽管我本身并不是说这比使用 up_list
实现更有利)。然而,事情就是这样定义的。
从 Ranges in Haskell (GHCi) 可以很清楚为什么 [2, 2..20]
生成无限列表。
下一个值是相同的,这就是这段代码产生无限列表的原因。
而且看起来它并不关心限制,因为 [2, 2..2]
也会生成无限列表。
问题:
为什么下面的代码 [2, 2..(-20)]
生成空列表?
简而言之:这是预期的行为。
[x, y..z]
表达式是 enumFromThenTo x y z
和 enumFromThenTo :: a -> a -> a -> [a]
的语法糖。
对于 Integer
s 它的实现方式如下:
instance Enum Integer where # ... enumFromThenTo x y lim = enumDeltaToInteger x (y-x) lim
所以它会调用 enumDeltaToInteger 2 0 (-20)
。 enumDeltaToInteger
is implemented with [src]:
enumDeltaToInteger :: Integer -> Integer -> Integer -> [Integer] enumDeltaToInteger x delta lim | <b>delta >= 0 = up_list x delta lim</b> | otherwise = dn_list x delta lim
所以它被认为是一个up_list
,并且up_list
会增加直到它达到大于lim
的值:
up_list :: Integer -> Integer -> Integer -> [Integer] up_list x0 delta lim = go (x0 :: Integer) where go x | <b>x > lim = []</b> | otherwise = x : go (x+delta)
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
.
所以文档说如果"step"是零个或多个,并且e1 > e3
,那么结果是空列表。
不过确实是"tricky"的情况。我个人同意使用 0
作为 "step" 的特例是有意义的(尽管我本身并不是说这比使用 up_list
实现更有利)。然而,事情就是这样定义的。