关于hFlush和惰性评估的问题

时间:2019-10-28 20:19:15

标签: haskell io monads 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

prompt'prompt''都在运行getLine之前刷新标准输出,但没有prompt。为什么会这样?

1 个答案:

答案 0 :(得分:7)

因为这不是您要的。自

prompt = (getLine <*) . (hFlush stdout <*) . putStrLn

我们可以添加一个参数来查看得到的结果:

prompt str = ((getLine <*) . (hFlush stdout <*) . putStrLn) str
           = getLine <* hFlush stdout <* putStrLn str

这要求按顺序运行动作getLinehFlush stdoutputStrLn str。 (然后,该操作序列的结果值就是getLine刚开始时的结果值。)您需要这样做:

prompt str = putStrLn str *> hFlush stdout *> getLine

或:

prompt = (*> getLine) . (*> hFlush stdout) . putStrLn

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