在GHCi和runhaskell中,getLine功能的区别是什么?

18

我刚刚遇到了一个我不理解的问题。

如果我在使用GHCi并使用getLine,我会得到以下结果:

Prelude> a <- getLine
Test<Backspace>oo<CR> -- the Backspace action results in a '^?'
Prelude> a
"Test\DELoo"

如果我在Haskell文件中写同样的话
module Main where

main :: IO ()
main = do a <- getLine
          putStrLn a

使用runhaskell运行脚本并输入相同的内容,回退键会删除预期的“t”。

为什么会有差异?

1个回答

23

这是因为GHCi和GHC在缓冲行为上有所不同。 GHCi 默认使用 NoBuffering 来处理标准输入流 (stdin),而使用 GHC 编译的二进制文件或者 runhaskell 则默认使用 LineBuffering。如果你想要显式地设置

hSetBuffering stdin NoBuffering

在您的 Haskell 程序中,您将能够复制 GHCi 的行为。如果您这样做

hSetBuffering stdin LineBuffering

在GHCi中,你会遇到许多不必要的副作用,但可以复制runhaskell的行为。


2
你说我会有“很多不必要的副作用”,它们只是在ghci中不需要,还是在编译版本中有一些保护措施 - 你能详细解释一下吗? - epsilonhalbe
无论你做还是不做,我会尽快接受这个答案! - epsilonhalbe
2
它们在GHCi中是不需要的。这会干扰GHCi本身读取输入的方式,因此当您键入要运行的内容时,只有在按下Return键后才会看到它们显示出来。 - kosmikus
在使用GHCi的getLine时,是否有一种方法可以删除/修改您的输入? - jscs
@JoshCaswell 你是什么意思?例如 haskeline 提供的行编辑功能是指什么? - kosmikus
我会看一下,谢谢。我的需求可能更基础:我正在学习《表达之道》这本书,它使用了 getLine,我遇到了这个问题。不过这只是一个小问题,不会影响整体进度。 - jscs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接