来自Windows,我最近通过bash(ghc 7.10)安装了名为Peppermint和Haskell-Platform的Linux发行版,但是ghci中的ghci stdin肯定有问题,因为:
interact $ take 0
抛出错误但是
interact $ take 1
没有。
此外,如果我在写入stdin时使用backspace
,arrows
或任何其他控制按钮,则输入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'
答案 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)来向行添加一个字符或执行一些行编辑命令并死掉,因为它正在处理一个半封闭的句柄。因此,一个较弱的生物会摔倒,生命之轮会继续下去。