У меня возникают трудности с пониманием ленивой оценки 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
является map
и 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-ю строку без увеличения потребления памяти?
Эксперимент под руководством Дерека заключается в следующем. С переключением 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