gpt4 book ai didi

haskell - 困惑 : Haskell IO Laziness

转载 作者:行者123 更新时间:2023-12-02 12:09:10 30 4
gpt4 key购买 nike

我在理解 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
执行

wordsmap在字符流上,该程序惰性地使用常量内存。 constant memory usage

但是当我添加参数t时,情况发生了变化。我的期望是因为 t 是惰性流上的 mapwords,并且 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

memory is increasing

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

memory keeps increasing

Q2) (:)[,] 在惰性求值方面有何不同?

欢迎任何意见。谢谢

[编辑]

Q3) 那么,是否可以先处理第四行,然后处理处理第二行,而不增加内存消耗?

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

enter image description here

最佳答案

为了回答您的第一个问题,就垃圾收集器而言,t 一直处于事件状态,直到您到达 consumeList 的末尾。这没什么大不了的,因为 t 会是一个 thunk 指向要做的工作,但这里的问题是 thunk 现在让 y 保持事件状态并且 getContents 必须实际读取 y 才能到达 k。在您的第一个示例中, y 可能会在读入时被垃圾收集。(作为一个实验,如果您在中切换 yk在这个示例中,我怀疑您会看到与第一个示例非常相似的行为。)

对于你的第二个问题,let [x,y,z,k] = ... 表示“(无可辩驳地)匹配恰好四个元素的列表”。这意味着当您强制 k 时,它需要(此时)检查是否没有其他元素,这意味着它需要读入与 k 对应的所有输入在它开始处理之前。在前面的情况下,let (x:y:z:k:xs) = ... 它可以立即开始处理 k,因为它不必首先检查xs[] 还是 (_:_)

关于haskell - 困惑 : Haskell IO Laziness,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34939258/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com