无限列表容量是否构建在`Ord`类型类中,或者是haskell对数字的定义的乘积?

时间:2013-07-25 21:20:09

标签: haskell lazy-evaluation recursive-datastructures

我试图围绕着如何获得无限名单来解决这个问题......这是我的路障:

您有一个A类型的列表,而A实现了Ord类型类。您可以像这样描述一系列有序元素(例如,intergers):

[1..6]

等同于......

Cons 1 (Cons 2 (Cons 3 (Cons 4 (Cons 5 (Cons 6 (Empty))))))

haskell如何知道如何构建无限列表? haskell能否创建支持Ord的任何数据类型的无限列表?

3 个答案:

答案 0 :(得分:6)

Haskell“创建”无限列表,因为它不需要创建任何元素。例如,让我们来看看head [1..]的扩展,它在Haskell中产生1,在严格语言中产生无限循环。

head [1..]

===                                 [expand `head`, literally 
                                     just inline the definition]
case [1..] of
  []        -> error "empty list"
  (x : xs)  -> x

===                                 [evaluate [1..] one step,
                                     check if it matches the case]
case 1:[2..] of
  []        -> error "empty list"
  (x : xs)  -> x

===                                 [it does!]

(1 : [2..]) -> 1

===                                 [fin]

1

请注意,与大多数语言相比,这是非常落后的,这些语言首先攻击[1..]的定义,而不是攻击head

你可以写[x..]不是Ord类型类中的任何类型(只能告诉我们两个事物是大于还是小于一个)而是Enum中的任何类型} typeclass as [x..]转换为enumFrom x enumFrom :: Enum a => a -> [a]

答案 1 :(得分:4)

离开语法含糖[a..b]的东西可能会容易一些,并想一想前奏中的一个简单函数:

repeat :: a -> [a]
repeat x = x : repeat x

你现在应该忘记评估并开始以声明的方式思考,即将上述内容想象成数学函数,可以阅读:

  

“重复x”表示“x”与“重复x”相对应

是的,“懒惰评估”是我们所说的能够让我们表达这一点的内容,但理想情况下,我们真的只想忘记评估并思考我们的代码意味着什么。在命令式编程中,您有义务始终考虑评估。

这或多或少是您的[1..] desugars:

enumFrom n = n : enumFrom (succ n)

你可以在@ tel的回答中看到编译器如何扩展它。

答案 2 :(得分:0)

对于来自面向对象背景的人来说,无限列表的概念应该易于理解。

诀窍是将Haskell列表视为数组甚至是链表,而不是迭代器对象。迭代器对象是一个具有两个方法的对象hasNextgetNext

通常,在有限数量的hasNext调用之后,迭代器的False将返回getNext。如果你认为迭代器绑定到“真实”集合(如数组,哈希映射,文件等),那肯定是正确的。

但是没有任何东西固有地迫使迭代器变得“有限”。您可以非常轻松地实现无限迭代器。在类似Haskell的伪代码中:

object Iterator where
  hasNext _ = True
  getNext = do
    state <- get
    put (state + 1)
    return state

如果你不知道这个迭代器是如何实现的,只要通过观察它的行为,你就会认为它与无限(或至少非常巨大)的集合有关。但它只是 - 一个返回连续数字的对象。

另一个类似的类比是UNIX中的特殊文件,例如/dev/zero/dev/random。如果它们与硬盘上的真实文件绑定,则磁盘必须是无限的。但它们不是 - 相反,内容是由内核按需生成的,您可以根据需要尽可能多地使用它。

Haskell的惰性列表与此完全相同,除了它们还“缓冲”所有生成的值,以便您可以重复检查它们而无需重复评估。