xji*_*xji 5 io haskell loops user-input input
我interact用来逐步处理一些用户输入(具体来说,它是一个国际象棋程序).但是,我还没有找到一种方法来处理用户可能想要突破循环并从头开始匹配国际象棋的情况.
当我在ghci中执行正常程序时,按下Ctrl-C将不会退出整个ghci,但只会停止程序本身并允许我继续执行其他一些程序.但是,如果我Ctrl-C在控制台中按下该interact功能,则会显示以下消息:
^CInterrupted.
*Main>
<stdin>: hGetChar: illegal operation (handle is closed)
Run Code Online (Sandbox Code Playgroud)
然后我必须重新启动ghci.
我还想过捕获特殊的用户输入,例如"退出",但是,由于类型interact是interact :: (String -> String) -> IO (),输入必须首先通过键入的函数(String -> String),我还没有找到一种方法来通知主要的IO它应该退出.
我应该如何突破interact?或者interact不打算以这种方式使用,我应该组成自定义IO功能?
我应该如何突破
interact?
你不能.你能想到的interact f作为getContents >>= putStrLn . f.而getContents将关闭在手柄上stdin.任何有关阅读的进一步操作都将失败
文字字符^ D显示在终端中
这是readline的一个问题.GHCI改变的缓冲方法stdin从LineBuffer以NoBuffering最佳地使用输入行.如果你想退出interact与^D,您需要更改的缓冲方法:
ghci> import System.IO
ghci> hGetBuffering stdin
NoBuffering
ghci> hSetBuffering stdin LineBuffering
ghci> interact id
hello world
hello world
pressing control-D after the next RETURN
pressing control-D after the next RETURN
<stdin>: hGetBuffering: illegal operation (handle is closed)
Run Code Online (Sandbox Code Playgroud)
或者
interact不打算以这种方式使用,我应该编写自定义IO函数?
是的,它不打算以这种方式使用.interact意味着使用所有输入并指示所有输出.如果要使用使用行方式输入,可以编写自己的行式交互方法(或使用外部库):
import Control.Monad (when)
interactLine :: (String -> String) -> IO ()
interactLine f = loop
where
loop = do
l <- getLine
when (l /= "quit") $ putStrLn (f l) >> loop
Run Code Online (Sandbox Code Playgroud)