Reputation: 10941
I am testing a program. Specifically, I am testing a function in isolation. It requires a handle that can be both read and wrote. The problem is, stdin
or stdout
alone can't do the job. I don't want to rewrite my code just because of such a test, nor do I want to have to open up a socket just for a test either. Also, the program isn't usable yet (have the functions are undefined) so I can't just test it by running it.
What is a handle that gets it input from stdin
and output from stdout
in haskell.
Upvotes: 7
Views: 2039
Reputation: 35089
One simple way to do this is to use a Pipe
to abstract out reads and writes to handles. One type you can use is:
example :: Monad m => Pipe String String m ()
For example, let's say that your original code looked something like this:
original :: IO ()
original = do
str1 <- getLine
str2 <- getLine
putStrLn (str1 ++ str2)
The new pipes
version would look like this:
import Pipes
example :: Monad m => Pipe String String m ()
example = do
str1 <- await
str2 <- await
yield (str1 ++ str2)
Then, you can test it purely like this:
>>> import qualified Pipes.Prelude as Pipes
>>> Pipes.toList (each ["Hello, ", "world!"] >-> example)
["Hello, world!"]
... or you can test it with real input and output:
>>> runEffect $ Pipes.stdinLn >-> example >-> Pipes.stdoutLn
Hello, <Enter>
world!<Enter>
Hello, world!
This lets you keep your main logic pure, and then choose whether or not to run it purely or impurely.
Upvotes: 18