How can I get input right when it is typed in Haskell? - haskell

I have written a Brainfuck interpreter in Haskell, but it only operates on the input once I hit Ctrl-D to signal EOF. How can I make the program act on each character when it is typed?
Here is the source. To use the program, give a file to interpret as an argument or type your program in the first line of stdin.

It sounds like your input is being buffered. You can modify the buffering mode of a file handle with System.IO.hSetBuffering. If you are reading from standard input, for instance, then you could disable buffering with:
import System.IO
hSetBuffering stdin NoBuffering

getLine waits for a newline character to be typed (\n), because what if the user typed a bunch of characters, but never pressed enter? Then it would be an error if some of the "line" had already be processed, if that "line" wasn't a line after all.
You should use getContents instead which will return everything that is typed at the terminal.
Also, you are using the following line:
then hGetContents =<< openFile (head args) ReadMode
This will open a file and never close it. This is fine for your short program, but it might be a better idea for the future to get used to doing this:
then readFile $ head args

Related

Reading stdin in ghci on Linux is broken

Comming from Windows, I have recently installed linux distribution named Peppermint and Haskell-Platform via bash (ghc 7.10) but there must be something wrong with ghci stdin in ghci because :
interact $ take 0
throws an error but
interact $ take 1
does not.
Furthermore, if I use backspace, arrows or any other control button when writing into stdin, it enters the char symbol. For example backspace enters ^? into ghci instead of deleting the last char typed...
...#... ~ $ 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'
Regarding the control code literals, this is because you've managed to escape all of the line editors (readline, Haskeline) that would usually interpret your key presses.
I don't know the particulars, but invoking GHCi is something like starting a subshell with bash --noediting. This allows GHCi to receive raw key presses without interference from the readline library. This is done because Haskeline—which GHCi uses in place of readline—can be configured with things like tab completion for available functions more easily (you knew GHCi provided tab completion, right?).
Calling getLine from GHCi then effectively drops through a trap door and dodges Haskeline completely by going straight to stdin. There is, after all, only one stdin. You're now typing directly into an unbuffered terminal.
Getting back to your first concern, there being only one stdin is also why GHCi immediately keels over after printing the Prelude> prompt. interact (which uses hGetContents behind the scenes) claims that it will address all of the input that will ever come through the handle (stdin) as one big lazy String. Effectively there can be no remaining input on the handle that interact hasn't already claimed to deal with, so the handle is immediately put into a “semi-closed” state. It's not closed (there could still be more input that will be read as part of that lazy String interact gets!) but it is closed to any newcomers, otherwise input would get duplicated (interact and new readers of the handle such as getLine would get the same line!).
Back to GHCi, after having used interact, stdout is still fine so the prompt gets printed as usual, then GHCi leans on Haskeline to return a line for processing. Haskeline (as a line editor) calls a blocking getChar (iirc) to either add a character to the line or perform some line editing command and dies because it's addressing a semi-closed handle. Thus a weaker creature does fall and the great wheel of life rolls on.

Why does Haskell NoBuffering option still seem to buffer?

I loaded up a file in ghci with the following:
h <- openFile "somefile.txt" ReadMode
hSetBuffering h NoBuffering
I then modified and saved somefile.txt in a text editor. When I call hGetChar several times in ghci, I receive the old characters of the file (as if the entire file was buffered when I opened it). I expected to calls of hGetChar to return the modified contents. Why is this not the case?
Edit:
The reason why it isn't showing the modified contents in the case decribed above is indeed because of the text editor. When the cat command is used instead (cat > somefile.txt), then the modified file contents is returned.
However, it does still seem to doing buffering. Say the file contents is as follows:
ABCDEFGHI
123456789
If I run hGetChar I get the 'A' as expected.
Now if I use cat (cat > somefile.txt) to change the contents to the following, and run hGetChar again, I would expect 'Z' but it's returning 'B':
AZZZZZZZZ
BufferMode is only relevant when writing to a handle, not when reading from it.
From [note Buffered Reading] in GHC.IO.Handle.Types:
Note that the buffering mode (haBufferMode) makes no difference when
reading data into a Handle. When reading, we can always just read all
the data there is available without blocking, decode it into the Char
buffer, and then provide it immediately to the caller.
The documentation for input BufferMode seems to be outdated.

Haskell Compiled IO-Action order and Flushing [duplicate]

This question already has answers here:
IO happens out of order when using getLine and putStr
(3 answers)
Closed 8 years ago.
I'm encountering strange behaviour with IO, within compiled Haskell code. Here's what's going on:
-- MyScript.hs
main = do
putStr "Enter your name: "
a <- getLine
putStrLn (a ++ " - that's a nice name!")
I run this in GHCi by calling main and it works as one would expect, first printing Enter your name: and then doing whatever it's to do afterwards. However, when I compile it with GHC (With and without --make), it first prompts for a line, and then prints everything at once, like this:
$ ./MyScript
Jimmy Johnson
Enter your name: Jimmy Johnson - That's a nice name!
To clarify, I want it to occur in the following sequence:
$ ./MyFixedScript
Enter your name: Jimmy Johnson
Jimmy Johnson - That's a nice name!
Could someone explain why this happens as it is, and how to sequence the IO the way that I would expect it to.
Note also that I've tried changing the first line of the do statement to _ <- putStr "Enter your name: ", but that still doesn't work.
The IO actions are happening in the correct order, the problem lies in how input and output pipes work. The string "Enter your name: " is written to the output buffer by putStr before the getLine, but the buffer hasn't necessarily been flushed. Adding hFlush stdout after the putStr will flush the buffer.
import System.IO
-- MyScript.hs
main = do
putStr "Enter your name: "
hFlush stdout
a <- getLine
putStrLn (a ++ " - that's a nice name!")
I have the exact same problem today, and it appears that it worked well when I was using putStrLn but stopped when I changed it to putStr. As other people said, it's not related to Haskell or GHC but how IO are flushed. According to the System.IO documentation there are 3 buffering mode :
line-buffering: the entire output buffer is flushed whenever a newline is output, the buffer overflows, a System.IO.hFlush is issued, or the handle is closed.
block-buffering: the entire buffer is written out whenever it overflows, a System.IO.hFlush is issued, or the handle is closed.
no-buffering: output is written immediately, and never stored in the buffer.
The default buffering mode is said to besystem dependent, but it seems that normal program are in line-buffering mode, whereas GHCI is in no-buffering mode. This explain because using putStrLn or putStr will flush or not.
To solve your problem, you can use hFlush stdout to flush explictitey (see Cirdec answer) or change the buffering mode once by doing hSetBuffering stdout NoBuffering. Obvioulsly the NoBuffering mode is not optimal but is probably enough for small toy program.

How do I use getContents to take input from the command line?

My program allows the user to specify a file which is read as input, however this is optional. If the user does not specify a file, I'd like to read input in from the command line.
I have this so far:
main :: IO()
main = do
(opts, mbArgs) <- parseCmdLine
input <-
case mbArgs of
Nothing -> getContents
Just file -> readFile file
This doesn't seem to be working. When a user doesn't stipulate a file, they are able to enter input, but there seems to be no way of terminating so that the program can then work on that input.
I thought that you had to press Ctrl+D, but that doesn't do anything.
Thanks for any help.
In a typical Unix-like terminal (such as Cygwin, at least in Cygwin's rxvt; not sure about the Windows Command Prompt), a Ctrl+D only sends EOF when you're at the start of a line. If you hit Enter and then Ctrl+D, it should work. If you want to send EOF without a newline, hit Ctrl+D twice in a row.
If it's not that, then there's presumably some other problem with your terminal; the code looks fine.
I'm going to write hammar's comment as an answer.
For me on windows, hitting ctrl+Z crtl+Z enter worked.

Haskell Console IO in notepad++

I've recently started to learn Haskell. I have this code
module Main
where
import IO
main = do
hSetBuffering stdin LineBuffering
putStrLn "Please enter your name: "
name <- getLine
putStrLn ("Hello, " ++ name ++ ", how are you?")
I'm using the GHC compiler together with the notepad++ editor. The problem is the interaction goes like this:
Process started >>>
Vlad
Please enter your name:
Hello, Vlad, how are you?
<<< Process finished.
As you can see, output is only written after I input something. This was a bit unexpected, as I was sure the program would first ask for my name, then I'd get to enter it and then it would say hello. Well, that's exactly what happens if I run the exe manually, yet not if I run it with notepad++ and use its console wrapper...
How can I make notepad++ display the output when it should, and not all of it just before the program terminates? Is this even possible?
Try setting stdout to LineBuffering! Also, loading your program in ghci instead runnign the compiled version doesn't seem to need any buffering at all...
By the way, I didn't know about the console in NPP - thanks for pointing me to it!
I'm not familiar with notepad++, but a quick and hacky method would probably be to do
hFlush stdout
after each putStrLn. You could even make the following method:
nppPutStrLn s = putStrLn s >> hFlush stdout

Resources