我具有相同功能的三个定义:
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之前刷新了stdout,但没有刷新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
!)