Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read and process user input infinitely in Haskell

Tags:

haskell

I would like my commandline Haskell program to function like this: program wait for user input,

  1. user type something, push "enter"
  2. Haskell process the input, shows the result on stdout
  3. Haskell waits for next user input
  4. If no more input, user terminate program by Ctrl+D

I tried getContents. But getContents wait for user to type all lines before processing them.

like image 978
McBear Holden Avatar asked Apr 17 '12 16:04

McBear Holden


People also ask

What is putStrLn in Haskell?

The function putStrLn takes a String and displays it to the screen, followed by a newline character (put a String followed by a new Line).

What is twice in Haskell?

Twice instead is an example of self-composition (function iteration), which you can express through f . f . But note that there are no overloaded functions in Haskell - Every function in one scope has exactly one type and implementation (though this type may be polymorphic).

How do I display lists in Haskell?

Example #1print("Demo to show list in Haskell !!") let list1 = [100, 50, 235, 167, 345, 909, 675, 20] let list2 = [1, 2, 3, 4, 5, 6, 7, 8, 9] let list3 = [1.1, 2.2, 3.3, 4.4, 5.5, 6.6] let list4 = [5, 10, 15, 20, 15, 30, 35, 40] let list5 = [123.4, 567.9, 56.0, 3.9, 76.9] print("printing list element !!")


1 Answers

There's a lot of confusion going on here. Let's try to clear things up.

I tried getContents. But getContents wait for user to type all lines before processing them.

The most likely thing here is that you've compiled your program, and didn't notice that the default buffering for output was block-buffering. This is easy to fix:

f line = putStrLn ("Hi, " ++ line ++ "!")

main = do
    hSetBuffering stdout LineBuffering -- or use NoBuffering
    putStrLn "Enter some names."
    input <- getContents
    mapM_ f (lines input)

You should use NoBuffering if you don't plan on printing a whole line (including newline) after each line of user input.

For a more precise answer, we'll need to see the code you tried that didn't work.

Q: But in my first try, I use: "interact show" and it doesn't work. Do you know why?
A: Because show will not return any output until its entire input has been exhausted.

This answer is not quite correct. The real answer is that show produces a string with no newlines in it! (Though the character sequence ['\\','\n'] does show up sometimes if the input is more than one line long.) So, for interact show, you really must use NoBuffering on stdout. For example, if you use this:

main = do
    hSetBuffering stdout NoBuffering
    interact show

...the program will print a bit more output after each line. You might also want to set stdin's buffering to NoBuffering (instead of the default LineBuffering), since show is productive enough that it really can produce more output after each keystroke.

like image 136
Daniel Wagner Avatar answered Nov 15 '22 09:11

Daniel Wagner