`stdin`和`stdout`处理程序

7
我正在测试一个程序,具体来说,我正在测试一项孤立的功能。它需要一个既能读又能写的句柄。问题是,仅使用"stdin"或"stdout"无法完成工作。我不想因为这样一个测试而重写我的代码,也不想仅仅为了进行测试就打开一个套接字。此外,该程序尚不可用(有些函数未定义),所以我不能通过运行它来进行测试。
在Haskell中,从"stdin"获取输入并从"stdout"输出的句柄是什么?

将代码更改为使用两个句柄,一个用于输入,一个用于输出,这样做是否不合理? - Code-Apprentice
嗯,我认为没有它会更干净。不过我想我可以这样做。 - PyRulez
1
我倾向于只是传递句柄(用于stdin/out/err),并将它们指向Data.Knob实例,如果我需要进行“纯”测试。 - Jon Purdy
1个回答

18

一个简单的方法是使用Pipe来抽象出对句柄的读写操作。可以使用的一种类型是:

example :: Monad m => Pipe String String m ()

例如,假设您的原始代码如下所示:
original :: IO ()
original = do
    str1 <- getLine
    str2 <- getLine
    putStrLn (str1 ++ str2)

新的 pipes 版本将如下所示:
import Pipes

example :: Monad m => Pipe String String m ()
example = do
    str1 <- await
    str2 <- await
    yield (str1 ++ str2)

然后,您可以像这样纯粹地进行测试:
>>> import qualified Pipes.Prelude as Pipes
>>> Pipes.toList (each ["Hello, ", "world!"] >-> example)
["Hello, world!"]

...或者您可以使用实际输入和输出进行测试:

>>> runEffect $ Pipes.stdinLn >-> example >-> Pipes.stdoutLn
Hello, <Enter>
world!<Enter>
Hello, world!

这样可以让你保持主要逻辑的纯净性,然后选择是否以纯粹或不纯粹的方式运行它。


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