关于hFlush和惰性评估的问题

Sar*_*lin 2 io monads haskell lazy-evaluation pointfree

我具有相同功能的三个定义:

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
Run Code Online (Sandbox Code Playgroud)

prompt'并且prompt''都在运行前刷新标准输出getLine,但是不能prompt。为什么是这样?

Dan*_*ner 7

因为那不是您要的。以来

prompt = (getLine <*) . (hFlush stdout <*) . putStrLn
Run Code Online (Sandbox Code Playgroud)

我们可以添加一个参数来看看我们得到了什么:

prompt str = ((getLine <*) . (hFlush stdout <*) . putStrLn) str
           = getLine <* hFlush stdout <* putStrLn str
Run Code Online (Sandbox Code Playgroud)

这要求运行的动作getLinehFlush stdout以及putStrLn str在这个顺序。(然后,该操作序列的结果值getLine就是开始时的结果值。)您需要这样做:

prompt str = putStrLn str *> hFlush stdout *> getLine
Run Code Online (Sandbox Code Playgroud)

要么:

prompt = (*> getLine) . (*> hFlush stdout) . putStrLn
Run Code Online (Sandbox Code Playgroud)

(实际上,在大多数情况下,默认缓冲是行缓冲或更少,而您正在调用putStrLn而不是putStr,因此这些解决方案实际上都不需要调用hFlush stdout!)