Haskell - 我如何摆脱互动?

Posted

技术标签:

【中文标题】Haskell - 我如何摆脱互动?【英文标题】:Haskell - How do I break out of interact? 【发布时间】:2016-09-09 09:34:42 【问题描述】:

我正在使用interact 逐步处理一些用户输入(具体来说,它是一个国际象棋程序)。但是,我还没有找到一种方法来处理用户可能只想跳出循环并从头开始这场国际象棋比赛的情况。

当我在 ghci 中执行正常程序时,按 Ctrl-C 不会退出整个 ghci,而只会停止程序本身并允许我继续执行其他一些程序。但是,如果我在控制台中按Ctrl-C 并启用interact 功能,则会显示以下消息:

^CInterrupted.
*Main> 
<stdin>: hGetChar: illegal operation (handle is closed)

然后我必须重新启动 ghci。

我也想过捕获特殊的用户输入,例如“退出”,但是,由于interact 的类型是interact :: (String -&gt; String) -&gt; IO (),所以输入必须先通过类型为(String -&gt; String) 的函数,而我没有' t 找到了一种方法让该函数通知主 IO 它应该退出。

我应该如何摆脱interact?还是 interact 不打算这样使用,我应该编写自定义 IO 函数?

【问题讨论】:

你试过 -D 吗? @Carsten 似乎什么也没做 @Carsten 文字字符 ^D 显示在终端中。 您使用的是哪个操作系统? 我通常认为interact 是过去的爆炸。这些天来它很少见,我认为它仍然在这里主要是为了向后兼容。 【参考方案1】:

我应该如何突破interact

你不能。您可以将interact f 视为getContents &gt;&gt;= putStrLn . f。而getContents 将关闭stdin 上的句柄。任何有关读取的进一步操作都将失败。

文字字符 ^D 显示在终端中

这是 readline 的问题。 GHCi 将stdin 的缓冲方法从LineBuffer 更改为NoBuffering 以优化使用readline。如果想用^D退出interact,需要改变缓冲方式:

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)

或者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

【讨论】:

我认为interact 这个名字有点误导。通常,当您想到“交互”时,您会想到比这个函数提供的更复杂的东西。 @JIXIang:它或多或少是作为命令行管道中的东西进行交互的,例如program1 | haskellprogram | program3。不过,这并不是真正的人工输入。 @EPo 不,那是来自Control.Monad

以上是关于Haskell - 我如何摆脱互动?的主要内容,如果未能解决你的问题,请参考以下文章

如何在haskell(光泽)中加载图像数组?

如何在 Haskell 中表示两棵树之间的映射?

如何在 haskell 中打印列表?

如何获取 Haskell 代码字符串(连同值)

如何展平haskell中的列表列表

如何正确使用haskell中的长度函数?