【发布时间】:2011-10-11 23:55:28
【问题描述】:
我对 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]
【问题讨论】:
我对 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]
【问题讨论】:
基本上,因为[10..1] 被转换为enumFromTo 10 1,它本身具有通过从(包括)10。
而[10, 9..1] 被转换为enumFromToThen 10 9 1,它将计数步长明确声明为9-10,即-1(对于enumFromTo,它被硬编码为+1)
可以在 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]
对于
Int和Integer这两种类型,枚举函数的含义如下:
序列
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,则列表为空。
【讨论】:
算术序列符号只是 Enum 类中函数的语法糖。
[a..] = enumFrom a
[a..b] = enumFromTo a b
[a, b..] = enumFromThen a b
[a, b..c] = enumFromThenTo a b c
至于为什么它们没有被定义为自动反转,我只能推测,但这里有一些可能的原因:
如果a 和b 在别处定义,则很难一眼看出[a..b] 将朝哪个方向发展。
它有更好的数学属性可以推理。您不必添加特殊情况来处理顺序颠倒的情况。
【讨论】:
如果要生成从a 到b 的列表,无论是否为a < b,都可以使用如下:
[a, a + (signum $ b - a)..b]
【讨论】:
a = b,这会产生一个无限列表。
[a, a + (1 / (1 / signum $ b - a)))..b] 如果 a = b 则失败
对于新手。
要列出从 20 到 1 的所有数字,你不能这样做
[20..1]
你必须这样指定:
[20,19..1]
【讨论】: