我在理解 Haskell 惰性评估方面遇到了困难。
我写了简单的测试程序。它读取 4 行数据,第二和第四输入行有很多数字。
consumeList :: [Int] -> [Int] -> [Int]
consumeList [] _ = error "hi" -- to generate heap debug
consumeList (x:xs) y = consumeList xs y
main = do
inputdata <- getContents
let (x:y:z:k:xs) = lines inputdata
s = map (read ::String->Int) $ words $ k
t = []
print $ consumeList s t
words
并且map
在字符流上懒惰地执行,该程序使用常量内存。
但是当我添加参数t
时,情况发生了变化。我的期望是因为t
ismap
并且words
在惰性流上,并且t
没有在 中使用consumeList
,所以这个更改不应该改变内存使用。但不是。
consumeList :: [Int] -> [Int] -> [Int]
consumeList [] _ = error "hi" -- to generate heap debug
consumeList (x:xs) y = consumeList xs y
main = do
inputdata <- getContents
let (x:y:z:k:xs) = lines inputdata
s = map (read ::String->Int) $ words $ k
t = map (read ::String->Int) $ words $ y
print $ consumeList s t -- <-- t is not used
Q1) 为什么这个程序在t
完全不使用的时候一直在分配内存?
我有另一个问题。当我模式匹配惰性流时[,]
,不使用(:)
内存分配行为会改变。
consumeList :: [Int] -> [Int] -> [Int]
consumeList [] _ = error "hi" -- to generate heap debug
consumeList (x:xs) y = consumeList xs y
main = do
inputdata <- getContents
let [x,y,z,k] = lines inputdata -- <---- changed from (x:y:..)
s = map (read ::String->Int) $ words $ k
t = []
print $ consumeList s t
Q2)在惰性评估方面有什么不同(:)
?[,]
欢迎任何意见。谢谢
[编辑]
Q3) 那么,是否可以先处理第 4 行,再处理第 2 行,而不增加内存消耗?
Derek指导的实验如下。通过从第二个示例切换 y 和 k,我得到了相同的结果:
consumeList :: [Int] -> [Int] -> [Int]
consumeList [] _ = error "hi"
consumeList (x:xs) y = consumeList xs y
main = do
inputdata <- getContents
let (x:y:z:k:xs) = lines inputdata
s = map (read ::String->Int) $ words $ y -- <- swap with k
t = map (read ::String->Int) $ words $ k -- <- swap with y
print $ consumeList s t