2011-07-24 61 views
19

我对Haskell很新。有人可以解释为什么定义这样的列表返回一个空列表Haskell递减范围

ghci> let myList = [10..1] 
ghci> myList 
[] 

但是,这个工作正常。

ghci> let myList = [10, 9..1] 
ghci> myList 
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] 

回答

34

基本上,因为[10..1]被转换为enumFromTo 10 1本身具有的语义通过取所有元素低于1从(包括)10向上计数(具有步长+1),其导致创建列表。

鉴于[10, 9..1]被转换为enumFromToThen 10 9 1其中明确规定的计数步长作为9-10,即-1(它是硬编码到+1enumFromTo

更精确的规范可以在Haskell的报告中找到( 6.3.4枚举类):

enumFrom  :: a -> [a]   -- [n..] 
enumFromThen :: a -> a -> [a]  -- [n,n'..] 
enumFromTo  :: a -> a -> [a]  -- [n..m] 
enumFromThenTo :: a -> a -> a -> [a] -- [n,n'..m] 

对于类型IntInteger,枚举函数甲肝E以下含义:

  • 序列enumFrom e1是列表[e1,e1+1,e1+2,...]

  • 序列enumFromThen e1 e2是列表[e1,e1+i,e1+2i,...],其中增量i是e2-e1。增量可以是零或负数。如果增量为零,则所有列表元素都是相同的。

  • 该序列enumFromTo e1 e3是列表[e1,e1+1,e1+2,...e3]。如果e1 > e3该列表为空。

  • 序列enumFromThenTo e1 e2 e3是列表[e1,e1+i,e1+2i,...e3],其中增量,i,是e2-e1。如果增量为正数或零,则列表在下一个元素大于e3时终止;如果e1 > e3列表为空。如果增量为负值,则列表在下一个元素小于e3时终止;该列表是空的,如果e1 < e3

+0

谢谢你,这是有道理的。乍一看,我认为这是非常愚蠢的表示,但我现在可以看到,它可以定义范围内的步骤的大小。很酷!非常兴奋Haskell现在:) – Christopher

11

算术序列符号仅仅是用于从Enum类函数语法糖。

[a..]  = enumFrom a 
[a..b] = enumFromTo a b 
[a, b..] = enumFromThen a b 
[a, b..c] = enumFromThenTo a b c 

至于为什么他们没有被定义为自动反转,我只能猜测,但这里有几个可能的原因:

  • 如果ab在别处定义,这将是更难一目了然地告诉[a..b]会走向哪个方向。

  • 它有更好的数学性质来推理。您不必为顺序颠倒时添加特殊情况。

2

如果你想生成ab列表无论a < b,您可以使用以下命令:

[a, a + (signum $ b - a)..b]

+1

请注意,这将产生一个无限列表,如果'a = b'。 – hammar

+0

@hammar我站在更正:) – dionyziz