IO monad and ordering [duplicate] - haskell

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).

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.

Weird buffering with prompt in haskell [duplicate]

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

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.

Read file line by line and execute those lines in Haskell

i want to read from a file (contains haskell commands per line). I want to read line by line and execute those and display the result
my following code is not working... print is not processing the command, it is just displaying it:
import System.IO
import Control.Monad
main = do
fileContents <- readFile "Instructions.txt"
mapM_ f (lines fileContents)
f line = do
putStrLn ("Processing Instruction:" ++ line)
print line
instruction file contains haskell commands.
You're probably looking for unsafeEval
http://hackage.haskell.org/packages/archive/plugins/1.5.1.3/doc/html/System-Eval-Haskell.html
But this is almost certainly definitely always a very bad idea for any real program, and not only goes against every guideline and rule of programming but also the fundamental principles of haskell programming.
If you just want something to read a file line by line and output the result, ghc already does this for you pretty well.
ghc -e "command" will execute the command and output to stdout, so it would be pretty easy to write a simple bash script to do this for you:
#!/bin/bash
# linebyline.sh
while read line; do
ghc -e "$line"
done
which you can run by:
cat myfile.txt | linebyline.sh
or you don't even need a separate script:
cat myfile.txt | while read line; do ghc -e "$line"; done
The solution is pretty simple: change print in f to a function which will interpret the line and execute it.
Iit is very easy to use system from System.Cmd and run commands via ghc - e. Your code then becomes
import System.IO
import System.Cmd
import Control.Monad
main = do
fileContents <- readFile "Instructions.txt"
mapM_ f (lines fileContents)
f line = do
putStrLn ("Processing Instruction:" ++ line)
system $ "ghc -e " ++ show line
You still need to add error checking and stuff like that but I'll leave those parts to you since they are not central to the question.

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

Resources