如何在Haskell中有效地重用stdin输入
我明白我不应该因为有关的错误而尝试重新读取如何在Haskell中有效地重用stdin输入,haskell,Haskell,我明白我不应该因为有关的错误而尝试重新读取stdin 例如,在下文中: main = do x <- getContents putStrLn $ map id x x <- getContents --problem line putStrLn x 但这会成为性能/内存问题吗?GHC是否必须将从stdin读取的所有内容保留在主存储器中 我想象第一次消费x时,GHC可以扔掉已经处理的x部分。因此,理论上,GHC只能使用少量的常量内存进行处理。但由于我们要一次
stdin
例如,在下文中:
main = do
x <- getContents
putStrLn $ map id x
x <- getContents --problem line
putStrLn x
但这会成为性能/内存问题吗?GHC是否必须将从stdin
读取的所有内容保留在主存储器中
我想象第一次消费x
时,GHC可以扔掉已经处理的x
部分。因此,理论上,GHC只能使用少量的常量内存进行处理。但由于我们要一次又一次地使用x
,GHC似乎不能扔掉任何东西。(也不能从stdin
中再次读取)
我对记忆含义的理解正确吗?如果是这样,是否有修复方法?是的,您的理解是正确的:如果重用
x
,ghc必须将其全部保存在内存中
我认为一个可能的解决办法是懒惰地(一次)消费它
假设您希望将x
输出到多个输出句柄hdl::[Handle]
。天真的做法是:
main :: IO ()
main = do
x <- getContents
forM_ hdls $ \hdl -> do
hPutStr hdl x
这里我们转置了循环:我们不迭代句柄(每个句柄迭代输入字符),而是迭代输入字符,并将每个字符打印到每个句柄
我还没有测试过它,但是这个表单应该可以保证我们不需要太多的内存,因为每个输入字符
c
都使用了一次,然后就被丢弃了。是的,它必须在内存中保留所有的stdin。我看不出修复是如何可能的:您是否希望您的程序丢弃数据并在以后仍然可以使用它?也许你正在寻找类似于dox的东西,你完全正确dox{cs粗略地说,我希望使用Haskell来实现UNIXtee
命令或它的一个变体。谢谢。我可以看到您的示例是如何工作的。但是我可能需要比这里的同步处理程序更复杂的东西。例如,如果我需要在第二轮中对流进行反转
或排序
,我猜是什么原因重新下线,它将中断。@tinlyxreverse
和sort
将强制累积所有输入,它们是教科书中的非流式操作。length
或word count等将起作用。感谢您的澄清。您认为如果我在大流上使用例如reverse
,我会得到相同的mem吗不管怎样,不管它是否在第二轮中使用?是的。只是do{cs
main = do
x <- getContents
putStrLn $ map id x
putStrLn x
main :: IO ()
main = do
x <- getContents
forM_ hdls $ \hdl -> do
hPutStr hdl x
main :: IO ()
main = do
x <- getContents
forM_ x $ \c -> do
forM_ hdls $ \hdl -> do
hPutChar hdl c