懒惰,单词读取(在交互中)所有输入,或只是需要什么?

时间:2018-05-23 23:37:02

标签: haskell

我开始学习Haskell,我正在努力理解 这些功能做了多少工作(特别是关于 懒惰的概念)。请参阅以下程序:

main::IO()
main = interact ( head . words)

这个程序会读取输入中的所有输入还是只读取第一个单词?

2 个答案:

答案 0 :(得分:3)

只是第一个字:

% yes | ghc -e 'interact (head . words)'
y
%

但要注意:这依赖于一个名为"懒惰的IO"这只与纯代码中的懒惰技术有关。纯函数在默认情况下是懒惰的,你必须努力使它们严格; IO是严格的IO"默认情况下,你必须努力使其懒惰IO。少数库函数(特别是interact(h)getContentsreadFile)已经付出了这些努力。

It also has some problems with composability.

答案 1 :(得分:3)

从概念上讲,它只读取它所需要的内容。但它可能使用缓冲区来执行此操作:

$ yes | strace -feread,write ghc -e 'interact (head . words)'
...
[pid 61274] read(0, "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8096) = 8096
[pid 61272] write(1, "y", 1y)            = 1
[pid 61272] --- SIGVTALRM {si_signo=SIGVTALRM, si_code=SI_TIMER, si_timerid=0, si_overrun=0, si_value={int=0, ptr=0}} ---
[pid 61272] write(5, "\376", 1)         = 1
[pid 61273] read(4, "\376", 1)          = 1
[pid 61273] +++ exited with 0 +++
[pid 61274] +++ exited with 0 +++
[pid 61276] +++ exited with 0 +++
+++ exited with 0 +++

这表明(在Linux系统上)程序将自己分成多个线程,其中一个从stdin读取8KiB数据,然后另一个输出第一个字。主要原因是反复阅读少量是非常低效的。但是,终端和套接字等异步源可能会产生较少量的数据:

$ strace -f -e trace=read,write -e signal= ghc -e 'interact (head . words)'
...
hello program
Process 61594 attached
[pid 61592] read(0, "hello program\n", 8096) = 14
[pid 61590] write(1, "hello", 5hello)        = 5

在这种情况下,终端层在第一个换行符处完成读取,即使缓冲区仍然是8KiB大。由于这足以确定第一个单词的数据,因此无需进一步读取。