Weird buffering with prompt in haskell [duplicate] - haskell

This question already has answers here:
Why doesn't Haskell sequence these IO actions properly?
(2 answers)
Closed 7 years ago.
I was playing around in Haskell and noticed something weird. I've defined a simple prompt function below.
-- file: test.hs
main :: IO ()
main = putStrLn . ("Hello, " ++) =<< (putStr "Name: " >> getLine)
When I runhaskell this, it works as expected, printing the prompt, waits for my input, then prints the greeting.
$ runhaskell test.hs
Name: kwarrtz
Hello, kwarrtz
When I compile it, however, things get weird. When I run it, it doesn't print the prompt, instead giving me a blank line and waiting for input. When I type my name and hit enter, it prints the prompt and the greeting, on the same line. In otherwords, the getLine happens before the putStr.
$ ghc test.hs
$ ./test
kwarrtz
Name: Hello, kwarrtz
Any thoughts on what's happening? I imagine it has something to do with the line buffering on my terminal, but I'm not sure how (that or I've just made some really ridiculous mistake in my code).
I'm running GHC 7.8.3 on Mac OS X El Capitan and using the default Terminal app.

Buffering.
hSetBuffering stdout NoBuffering
I think you can get all that from System.IO

Related

Why doesn't my Haskell cmd line program get arguments from Vim Bang?

Vim has the possibility to let you replace selected text with the output of an external program. I'd like to take advantage of this with programs that I'd write in Haskell. But it doesn’t get the selected text as args.
-- show-input.hs
module Main where
import System.Environment
main = do
input <- getArgs
putStr ("Input was: " ++ (show input))
When I run it from the command line (NixOS GNU/Linux, BASH), I get the expected behavior:
$ ./show-input test
Input was: ["test"]
When I select some text in Vim and invoke :'<,'>!~/show-input, I get this :
Input was: []
There is something weird here, but I can't tell if it is from the way Vim passes arguments or from the way Haskell gets them. I have tried with both console Vim and graphical gVim (8.0.1451), with the same result.
NB: I can successfully use Vim Bang! with other external programs, such as grep. It works great.
---
Correct version after chepner's answer
So, for anyone interested, just replace getArgs with getContents and you get your input all in a string (instead of a list of strings).
module Main where
import System.Environment
main = do
input <- getContents
putStr ("Input was: " ++ (show input))
The ! command sends the seleted text to the program via standard input, not as a command line argument. The command line equivalent would be somecommand | ./show-input.

IO monad and ordering [duplicate]

I have the following code:
main = do
putStr "Test input : "
content <- getLine
putStrLn content
When I run it (with runhaskell) or compile it (ghc 6.10.4) the result is like this:
asd
Test input : asd
Why is Test input : asd being printed after asd?
In the code sample on http://learnyouahaskell.com/, which uses putStr, the getLine's presented output is different than mine. When I use putStrLn the program works as expected (print, then prompt, and print).
Is it a bug in ghc, or it is the way that it should work?
This is because ghci disables buffering, while a program compiled with ghc has line buffering by default. You can see this by running this:
import System.IO
main = print =<< hGetBuffering stdout
In ghci you see NoBuffering while with runghc you get LineBuffering. Since the newline character doesn't print until after the user input, the prompt doesn't either.
Fix it by adding hFlush stdout after your prompt (or disable buffering with hSetBuffering stdout NoBuffering, but that’s probably bad).

Deleting items in stdin with haskell

I have a bit of code in my haskell program like so:
evaluate :: String -> IO ()
evaluate = ...
repl = forever $ do
putStr "> " >> hFlush stdout
getLine >>= evaluate
Problem is, when I press the delete key (backspace on windows), instead of deleting a character from the buffer, I get a ^? character instead. What's the canonical way of getting delete to delete a character when reading from stdin? Similarly, I'd like to be able to get the arrow keys to move a cursor around, etc.
Compile the program and then run the compiled executable. This will give the correct behavior for the Delete key. For some reason interpreting the program screws up the use of Delete.
To compile the program, just invoke ghc like this:
$ ghc -O2 myProgram.hs
This will generate a myProgram executable that you can run from the command line:
$ ./myProgram
That will then give the correct behavior for Delete.

Prompt message disappears in compiled executable?

I have a Haskell program that shows a prompt and then accepts input from the command line. I'm doing this as:
main = do putStr "Please enter program source file name: "
programFileName <- getLine
programFileHandle <- openFile programFileName ReadMode
program <- hGetContents programFileHandle
putStr "Please enter initial file configuration file name: "
initConfigFileName <- getLine
initConfigFileHandle <- openFile initConfigFileName ReadMode
initConfigStr <- hGetContents initConfigFileHandle
print (evaluateProgram (lines program) (readReg initConfigStr))
When I run it on the GHCi interpreter, the prompts show up fine and I am able to enter my inputs (and everything else works).
e.g.
*Main> main
Please enter program source file name: sum.urm
Please enter initial file configuration file name: sum.conf
9
When I compile it though (on Mac OS X or Windows), it produces an executable that does not show my prompts. It waits for the two input strings, and then once I have put in the valid filenames, it prints the prompts and the result.
e.g.
$ ./a.out
sum.urm
sum.conf
Please enter program source file name: Please enter initial file configuration file name: 9
Any ideas why this is happening?
For the curious, I was implementing an Unlimited Register Machine in Haskell.
The standard output stream, stdout, is line buffered by default. That means that it will only be written to the console every time you output a \n character, or finally when the program terminates. You can fix this by importing System.IO and doing hFlush stdout after every putStr that doesn't contain a \n at the end.
This is a buffering issue. Here are related questions, with several choices for solutions:
Why isn't my IO executed in order?
Execution order with (>>=) not what I expected

Haskell line won't execute: do { n <- readLn ; print (n^2) }

I've been following a Learn Haskell in 10 Minutes tutorial. Everything was going well until I reached this line:
do { n <- readLn ; print (n^2) }
It won't execute in ghci, and in Leksah I get the following error.
Parse error: naked expression at top level
I've tried updating cabal and installing foo, but the problem continues.
Your help would be greatly appreciated.
I'm using Ubuntu 11.10.
It's not freezing, it's waiting for input. Try typing a number and pressing Enter.

Resources