-6ren">
gpt4 book ai didi

haskell - 如何理解 Haskell 中的流

转载 作者:行者123 更新时间:2023-12-04 09:58:35 25 4
gpt4 key购买 nike

我正在读《学好 Haskell》第 9 章:输入和输出。有一个解释流的示例代码:

main = do   
withFile "something.txt" ReadMode (\handle -> do
contents <- hGetContents handle
putStr contents)

书上说:

That's why in this case it actually reads a line, prints it to the output, reads the next line, prints it, etc.

但是在之前的内容中,对于同一个例子,也是这样说的:

That's really cool because we can treat contents as the whole contents of the file, but it's not really loaded in memory.

我是函数式编程的新手,对此我真的很困惑,为什么我们可以采用 contents如果一次读取一行,作为全部内容?我虽然contentscontents <- hGetContents handle只是一行的内容,Haskell是把每一行的内容都存到暂存器还是别的什么地方?

最佳答案

How to understand stream in Haskell

您可以将其视为一个函数,它在被调用时返回一些 结果(不是全部)以及一个回调函数 以在您需要 时获取其余部分。因此,从技术上讲,它会为您提供全部内容,但一次提供一大块,并且只有在您要求其余部分时才会提供。

如果 Haskell 没有 non-strict semantics ,你可以通过类似的方式实现这个概念:

data Stream a = Stream [a] (() -> Stream a)

instance (Show a) => Show (Stream a) where
show (Stream xs _) = show xs ++ " ..."

rest :: Stream a -> Stream a -- ask for the rest of the stream
rest (Stream _ f) = f ()

然后假设您想要一个迭代整数的流。您可以返回前 3 个并推迟其余的直到用户要求:

iter :: Int -> Stream Int
iter x = Stream [x, x + 1, x + 2] (\_ -> iter (x + 3))

然后,

\> iter 0
[0,1,2] ...

但如果你一直要求剩下的,你就会得到全部内容

\> take 5 $ iterate rest (iter 0)
[[0,1,2] ...,[3,4,5] ...,[6,7,8] ...,[9,10,11] ...,[12,13,14] ...]

\> let go (Stream [i, j, k] _) acc = i:j:k:acc
\> take 20 . foldr go [] $ iterate rest (iter 0)
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]

这与引擎盖下的行缓冲是同一个故事。它读取并返回第一行,然后您可以请求下一行,然后是下一行,...所以从技术上讲,即使它一次只读取一行,您也可以获得全部内容。

关于haskell - 如何理解 Haskell 中的流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35683672/

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