是getLine
懒惰?是getLine懒惰?
说我对输入有很长的一行。这只是一个数字序列。我只需要总结3个第一个数字。请问getLine
是否高效,只读取该行的第一部分,或者我是否必须创建自己的函数来读取懒线,才能逐个读取字符?
如果我总结整条线,我的执行效率会高吗? (是否有一个开销由于一个读取字符一个?)
import Control.Applicative
main = do
line <- getLine'
print $ sum $ map read $ take 3 $ words line
getLine' :: IO String
getLine' = do
c <- getChar
if c == '\n' then return [] else (c:) <$> getLine'
我觉得'getLine'和''getLine''都是同样严格的。 IO操作不能懒惰地返回,除非通过利用一些'unsafe'函数 - 这被称为“惰性IO”,并且必须小心处理,因为实际的读取会由于懒惰而在后面开始,这可能会导致一些问题。惰性IO是(很)很难调试的。但是,您可以使用严格的自定义'get3Ints',它只能读取所需字符串的一部分。 – chi
'getLine'必须严格才能正确,正如chi所说,你的'getLine''表现完全一样。如果'getLine'不是严格的,那么你稍后做的纯计算会通过实现懒惰输入中的更多字符而导致IO。当你考虑其他的IO也可能会发生时,这将是一场噩梦,也从标准输入读取:哪些字符去哪里将是非常难以弄清楚。 – amalloy
参考[这个回答](https://codereview.stackexchange.com/a/120037/16551)看到更多关于'IO'和懒惰的信息。如果你想要一个懒惰的'getLine',它可能需要一个类似于'IO(ListT IO Char)'的类型,其中'data ListT m a = Nil |缺点(m(ListT m a))'(如果您以给定长度的块读取输入以提高效率,您也可以使用'ListT IO String'而不是'ListT IO Char'。 – gallais