在Linux上读取ghci中的stdin被打破了

时间:2016-08-07 16:22:06

标签: linux bash haskell

来自Windows,我最近通过bash(ghc 7.10)安装了名为Peppermint和Haskell-Platform的Linux发行版,但是ghci中的ghci stdin肯定有问题,因为:

interact $ take 0 抛出错误但是 interact $ take 1 没有。

此外,如果我在写入stdin时使用backspacearrows或任何其他控制按钮,则输入char符号。例如退格^? 输入ghci 而不是删除最后输入的字符...

...@... ~ $ ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude> interact $ take 0
Prelude> 
<stdin>: hGetChar: illegal operation (handle is closed)
...@... ~ $ ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
Prelude> readLn :: IO String 
euoe^?^?^[[1;5C^[[D^[[B -- here I tried to delete 'euoe'

1 个答案:

答案 0 :(得分:3)

关于控制代码文字,这是因为你设法逃脱了通常会解释你的按键操作的所有行编辑器(readline,Haskeline)。

我不知道具体细节,但调用GHCi就像用bash --noediting开始一个子shell。这允许GHCi接收原始按键而不受来自readline库的干扰。之所以这样做是因为Haskeline-- GHCi用来代替readline - 可以更容易地配置像可用函数的标签完成之类的东西(你知道GHCi提供了标签完成,对吧?)。

从GHCi调用getLine然后通过一个陷阱门有效地掉落并通过直接进入stdin完全避开Haskeline。毕竟,只有一个标准差。您现在正在直接键入无缓冲的终端。

回到第一个问题,只有一个stdin也是为什么GHCi在打印Prelude>提示后立即关注的原因。 interact(在幕后使用hGetContents)声称它会将通过句柄(stdin)传递的所有输入作为一个大的懒惰String。有效地,interact尚未声称要处理的句柄上没有剩余输入,因此句柄立即进入“半封闭”状态。它没有关闭(可能仍会有更多的输入将被视为懒惰的String interact的一部分!)但 对所有新手都关闭,否则输入将得到重复(interact和句柄的新读者,如getLine将得到相同的行!)。

回到GHCi后,在使用interact之后,stdout仍然正常,因此提示会照常打印,然后GHCi依靠Haskeline返回一行进行处理。 Haskeline(作为行编辑器)调用阻塞getChar(iirc)来向行添加一个字符或执行一些行编辑命令并死掉,因为它正在处理一个半封闭的句柄。因此,一个较弱的生物会摔倒,生命之轮会继续下去。