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

6 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
Run Code Online (Sandbox Code Playgroud)

(请注意'f'代表类型的功能

f :: Integral a => [a] -> [a] -> [a] 
Run Code Online (Sandbox Code Playgroud)

这不仅仅是++)

Haskell如何处理尝试打印setAllSorted?

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

或者,在获得setAllSorted的值之前,Haskell是否将所有内容保存在内存中?

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

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

pat*_*pat 9

头部setAllSorted必然小于或等于尾部的每个元素.因此,为了确定头,所有的setOnesetTwo必须计算.此外,由于所有集合都是不变的应用形式,我相信它们在计算后不会被垃圾收集.数字本身可能会在集合之间共享,但是将它们粘合在一起的利弊节点可能不会(有些人的运气取决于其定义f).

  • 即使它们是CAF,如果编译器可以确定在打印后不再引用它们,也可以收集它们.如果程序是`main = print setAllSorted`,GHC(带优化)很可能会垃圾收集不再需要的部分.然而,这只是峰值记忆的恒定因子减少. (2认同)

ham*_*mar 7

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

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

  1. 首先打印评估第一个元素setAllSorted.
  2. 由于这来自排序过程,因此需要setAll评估所有要素.(因为最小的元素可能是最后一个元素).
  3. 评估第一个元素setAll需要评估第一个元素setOne.
  4. 评估第一个要素setOne取决于如何f实施.它可能需要全部或不需要setAsetB评估.
  5. 在我们完成打印第一个元素后setAllSorted,setAll将进行全面评估.有没有更多的参考setOne,setTwo而较小的集,所以所有的这些都是现在有资格进行垃圾回收.第一个元素setAllSorted也可以回收.

因此从理论上讲,这段代码setAll大部分时间都会保留在内存中setAllSorted,setOne而且setTwo很可能在任何时候都占用一定的空间.根据实施情况f,对于较小的集合可能也是如此.