在Haskell中执行代码的默认方式

时间:2012-01-03 16:57:57

标签: performance haskell default

在以下通用代码中:

nat = [1..xmax]
xmax = *insert arbitrary Integral value here*   

setA = [2*x | x <- nat]
setB = [3*x | x <- nat]

setC = [4*x | x <- nat]
setD = [5*x | x <- nat]

setOne = setA `f` setB
setTwo = setC `f` setD

setAll = setOne ++ setTwo

setAllSorted = quicksort setAll

(请注意&#39; f&#39;代表类型

的功能
f :: Integral a => [a] -> [a] -> [a] 

这不仅仅是++)

Haskell如何处理尝试打印setAllSorted?

是否获取setA和setB的值,计算setOne,然后只将setOne的值保存在内存中(在计算其他所有内容之前)?

或者Haskell将所有内容保存在内存中,直到获得setAllSorted的值?

如果后者是这种情况,那么我将如何指定(使用main,执行函数以及所有其他IO的东西)来代替它?

我可以告诉程序计算和垃圾收集的顺序吗?如果是这样,我该怎么做?

1 个答案:

答案 0 :(得分:7)

由于懒惰,Haskell按需评估事物。您可以将最终完成的打印视为列出setAllSorted列表中的“拉动”元素,这可能会带来其他内容。

也就是说,运行此代码就是这样的:

  1. 首先打印评估setAllSorted的第一个元素。
  2. 由于这来自排序过程,因此需要评估setAll的所有元素。 (因为最小的元素可能是最后一个元素。)
  3. 评估setAll的第一个元素需要评估setOne的第一个元素。
  4. 评估setOne的第一个元素取决于f的实施方式。可能需要评估setAsetB的全部或全部内容。
  5. 在我们完成setAllSorted的第一个元素打印后,setAll将被完全评估。没有更多引用setOnesetTwo和较小的集合,因此所有这些现在都符合垃圾收集的条件。 setAllSorted的第一个元素也可以回收。
  6. 因此从理论上讲,此代码会在大多数情况下将setAll保留在内存中,而setAllSortedsetOnesetTwo可能只会占用一定量的空间随时。根据{{​​1}}的实现,对于较小的集合可能也是如此。