getLine 是懒惰的吗?
Is getLine lazy?
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
不是懒惰,但 getContents
是,并且它可以与 lines
和 words
等函数结合使用。因此,下面的程序只会读取足够的标准输入以从第一行获取(最多)三个整数并打印它们的总和:
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 个字符之前。换句话说,只有当您 仅 需要阅读第一行的第一位时,这种懒惰的行阅读才有用,如果这对您来说不是很明显 -- Haskell没有任何神奇的方法可以跳过第一行的其余部分进入第二行。
最后,请注意,对于上面的程序,如果第一行中的整数少于三个,它只会对这些数字求和,而不会尝试读取第一行之后的内容(我认为这是你想要什么)。如果您实际上并不关心行尾,只想对文件中的前三个数字求和,而不管它们是如何划分成行的,那么您可以将内容直接分解成这样的单词:
main = do contents <- getContents
let result = sum $ map read $ take 3 $ words contents
print (result :: Integer)
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
不是懒惰,但 getContents
是,并且它可以与 lines
和 words
等函数结合使用。因此,下面的程序只会读取足够的标准输入以从第一行获取(最多)三个整数并打印它们的总和:
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 个字符之前。换句话说,只有当您 仅 需要阅读第一行的第一位时,这种懒惰的行阅读才有用,如果这对您来说不是很明显 -- Haskell没有任何神奇的方法可以跳过第一行的其余部分进入第二行。
最后,请注意,对于上面的程序,如果第一行中的整数少于三个,它只会对这些数字求和,而不会尝试读取第一行之后的内容(我认为这是你想要什么)。如果您实际上并不关心行尾,只想对文件中的前三个数字求和,而不管它们是如何划分成行的,那么您可以将内容直接分解成这样的单词:
main = do contents <- getContents
let result = sum $ map read $ take 3 $ words contents
print (result :: Integer)