关于hFlush和lazy evaluation的问题
Question about hFlush and lazy evaluation
我得到了同一个函数的三个定义:
prompt :: String -> IO String
prompt = (getLine <*) . (hFlush stdout <*) . putStrLn
prompt' :: String -> IO String
prompt' str = do
putStrLn str
hFlush stdout
getLine
prompt'' :: String -> IO String
prompt'' str = putStrLn str >> hFlush stdout >> getLine
prompt'
和 prompt''
都在 运行 getLine
之前刷新标准输出,但不是 prompt
。这是为什么?
因为那不是你要的。自
prompt = (getLine <*) . (hFlush stdout <*) . putStrLn
我们可以添加一个参数看看我们得到了什么:
prompt str = ((getLine <*) . (hFlush stdout <*) . putStrLn) str
= getLine <* hFlush stdout <* putStrLn str
这要求 运行 按顺序执行 getLine
、hFlush stdout
和 putStrLn str
操作。 (那么该操作序列的结果值就是 getLine
一开始的任何结果值。)你想要这个:
prompt str = putStrLn str *> hFlush stdout *> getLine
或:
prompt = (*> getLine) . (*> hFlush stdout) . putStrLn
(其实大多数情况下默认的缓冲都是行缓冲或者更少,而你调用的是putStrLn
,而不是putStr
,所以none 这些解决方案实际上需要调用 hFlush stdout
!)
我得到了同一个函数的三个定义:
prompt :: String -> IO String
prompt = (getLine <*) . (hFlush stdout <*) . putStrLn
prompt' :: String -> IO String
prompt' str = do
putStrLn str
hFlush stdout
getLine
prompt'' :: String -> IO String
prompt'' str = putStrLn str >> hFlush stdout >> getLine
prompt'
和 prompt''
都在 运行 getLine
之前刷新标准输出,但不是 prompt
。这是为什么?
因为那不是你要的。自
prompt = (getLine <*) . (hFlush stdout <*) . putStrLn
我们可以添加一个参数看看我们得到了什么:
prompt str = ((getLine <*) . (hFlush stdout <*) . putStrLn) str
= getLine <* hFlush stdout <* putStrLn str
这要求 运行 按顺序执行 getLine
、hFlush stdout
和 putStrLn str
操作。 (那么该操作序列的结果值就是 getLine
一开始的任何结果值。)你想要这个:
prompt str = putStrLn str *> hFlush stdout *> getLine
或:
prompt = (*> getLine) . (*> hFlush stdout) . putStrLn
(其实大多数情况下默认的缓冲都是行缓冲或者更少,而你调用的是putStrLn
,而不是putStr
,所以none 这些解决方案实际上需要调用 hFlush stdout
!)