getLine懒惰吗?
假设我的输入有很长的线。只是数列而已。我只需要把三个第一个数字相加。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'发布于 2017-09-02 23:11:41
虽然getLine并不懒惰,但getContents是这样的,它可以与lines和words这样的函数组合。因此,下面的程序将只读取stdin的足够多,以便从第一行得到(最多)三个整数,并打印它们的和:
main :: IO ()
main = do contents <- getContents
let lns = lines contents
result = sum $ map read $ take 3 $ words $ head lns
print (result :: Integer)注意,如果您修改程序以访问后续的行--例如,如果您添加了:
putStrLn $ take 80 $ lns !! 1在程序底部打印第二行的前80个字符时,程序必须先读取第一行(在程序的最后两行之间挂起一点),然后再处理第二行的前80个字符。换句话说,只有当你只需要读第一行的第一部分,如果这对你来说不是很明显的时候,这个懒行阅读才会有用--哈斯克尔没有任何神奇的方法可以跳过第一行的其余部分进入第二行。
最后,请注意,对于上面的程序,如果在第一行中只有不到三个整数,它只会对这些数字进行求和,并且不会尝试读过第一行(我认为这正是您想要的)。如果您实际上并不关心行尾,只想将文件中的前三个数字相加,而不管它们是如何划分成行的,那么您可以将内容直接分解成这样的单词:
main = do contents <- getContents
let result = sum $ map read $ take 3 $ words contents
print (result :: Integer)https://stackoverflow.com/questions/45787011
复制相似问题