【发布时间】:2018-01-28 22:22:44
【问题描述】:
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”,必须小心处理,因为由于延迟实际读取将在稍后开始,这可能会导致一些问题。 Lazy IO 是出了名的难以调试。但是,您可以使用严格的自定义get3Ints,它只读取您需要的部分字符串。 -
getLine必须严格才能正确,正如 chi 所说,您的getLine'行为完全相同。如果getLine是非严格的,那么您稍后执行的纯计算将通过从惰性输入中实现更多字符而导致 IO。当您考虑到其他 IO 也可能在进行时,这将是一场噩梦,同时还从标准输入读取:哪些字符去哪里将非常难以弄清楚。 -
参见。 this answer 了解更多关于
IO和懒惰的信息。如果你想要一个懒惰的getLine,它可能需要一个类似于IO (ListT IO Char)的类型,其中data ListT m a = Nil | Cons a (m (ListT m a))(如果你以给定的块读取输入,你也可以使用ListT IO String而不是ListT IO Char长度更有效)。 -
到底什么是反对票?
标签: haskell io lazy-evaluation processing-efficiency