繁体   English   中英

如何了解Haskell中的流

[英]How to understand stream in Haskell

我正在阅读《学会哈斯凯尔》,第9章:输入和输出。 有一个用于解释流的示例代码:

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

书说:

这就是为什么在这种情况下,它实际上读取一行,将其打印到输出,读取下一行,将其打印,等等。

但是在以前的内容中,对于同一示例,它也表示:

这真的很酷,因为我们可以将内容视为文件的全部内容,但是它并没有真正加载到内存中。

我是函数编程的新手,对此我感到很困惑,如果一次读取一行内容,为什么我们可以将contents作为全部内容呢? 我虽然contentscontents <- hGetContents handle是一行刚的内容,并保存Haskell的每一行到临时存储器或别的什么内容?

如果一次读取一行,为什么我们可以将内容作为全部内容?

首先请注意,不必逐行读取内容(尽管有可能,稍后我会介绍)。 作者的意思是,即使没有将整个文件加载到内存中,您也可以从概念上假设变量contents具有文件的全部内容。 之所以可能这样做是因为文件的延迟流传输(如果您更感兴趣,可以在源代码中看到底层的详细信息。它基本上使用unsafeInterleaveIO来实现此目的)。

Haskell是否将每一行的内容保存到临时存储器或其他内容中?

这取决于所使用的缓冲类型。 根据文档,它取决于基础文件系统:

打开句柄时的默认缓冲模式取决于实现,并且可能取决于附加到该句柄的文件系统对象。 对于大多数实现,物理文件通常将被块缓冲,而终端通常将被行缓冲。

但是您可以使用hGetBuffering :: Handle -> IO BufferMode来查看自己所处的缓冲模式。

如何了解Haskell中的流

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

如果Haskell不具有非严格语义 ,则可以通过以下方式实现此概念:

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]

引擎盖下的线缓冲也是如此。 它读取并返回第一行,但是随后您可以要求下一行以及下一行,因此...从技术上讲,即使一次只读取一行,您也可以获得全部内容。

注意hGetHandle本身从不读取任何内容 它只是返回一个IO操作,该操作最终执行时将从文件中读取。 当联合putStrhGetContents handle >>= putStr (这简直是在do脱符号),你会得到一个IO动作,需要一个手柄,其内容输出到屏幕上。 在Haskell程序本身中,您从未指定过如何发生的。 它完全取决于Haskell运行时以及它如何执行您创建的IO操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM