【问题标题】:Strange result of List generation in HaskellHaskell中列表生成的奇怪结果
【发布时间】:2019-08-05 11:15:15
【问题描述】:

Ranges in Haskell (GHCi) 很清楚为什么 [2, 2..20] 会生成无穷大列表。

下一个值是相同的,这就是为什么这段代码会产生无穷大列表。

看起来它并不关心限制,因为[2, 2..2] 还生成无限列表。

问题:

为什么下面的代码[2, 2..(-20)]改为生成空列表?

【问题讨论】:

  • 因为它每次都会检查该值是否已经达到阈值。如果是(-20),它有。

标签: list haskell range ghci


【解决方案1】:

简而言之:这是有意的行为。

[x, y..z] 表达式是 enumFromThenTo x y zenumFromThenTo :: a -> a -> a -> [a] 的语法糖。

对于Integers,它的实现如下:

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
  | delta >= 0 = up_list x delta lim
  | 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 | x > lim   = []
                             | otherwise = x : go (x+delta)

Haskell'10 report on the Enum class中是这样描述的:

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

所以文档说如果“步”为零或更多,并且e1 > e3,那么结果就是空列表。

然而,这确实是一个“棘手”的案例。我个人同意将0 的特殊情况用作“步骤”是有意义的(尽管我本身并不是说这比使用up_list 实现更有利)。然而,这就是事物的定义方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 2014-12-13
    • 2020-04-09
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多