在以下通用代码中:
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的东西)来代替它?
我可以告诉程序计算和垃圾收集的顺序吗?如果是这样,我该怎么做?
答案 0 :(得分:7)
由于懒惰,Haskell按需评估事物。您可以将最终完成的打印视为列出setAllSorted
列表中的“拉动”元素,这可能会带来其他内容。
也就是说,运行此代码就是这样的:
setAllSorted
的第一个元素。setAll
的所有元素。 (因为最小的元素可能是最后一个元素。)setAll
的第一个元素需要评估setOne
的第一个元素。setOne
的第一个元素取决于f
的实施方式。可能需要评估setA
和setB
的全部或全部内容。setAllSorted
的第一个元素打印后,setAll
将被完全评估。没有更多引用setOne
,setTwo
和较小的集合,因此所有这些现在都符合垃圾收集的条件。 setAllSorted
的第一个元素也可以回收。因此从理论上讲,此代码会在大多数情况下将setAll
保留在内存中,而setAllSorted
,setOne
和setTwo
可能只会占用一定量的空间随时。根据{{1}}的实现,对于较小的集合可能也是如此。