Haskell do syntax and I/O - haskell

I was playing around with a simple program in Haskell:
hello :: String -> String
hello s = "Hello, " ++ (trim s) ++ "!\n"
trim :: String -> String
trim [] = []
trim s = head $ words s
main :: IO()
main = do putStr "\nPlease enter your name: "
name <- getLine
hstring <- return $ hello name
putStr hstring
This is the output I am expecting:
Please enter your name: John Doe
Hello, John!
This works as expected when I load the program into ghci. However when I compile the program using
ghc -o hello.exe hello.hs
it starts, waits for input, and then prints both prompts at the same time:
John Doe
Please enter your name: Hello, John!
Why is the behavior different between the interactive environment and compiler, and how can I make the compiler do what I want?
Thanks in advance for the help!

This is something of an FAQ. Your lines are being buffered. Use:
import System.IO
main = do
hSetBuffering stdout NoBuffering
...
Also, your code is a bit... unique. For example, you say:
hstring <- return $ hello name
putStr hstring
When you could do:
let hstring = hello name
putStr hstring
or just:
putStr $ hello name

Related

Menu option issue [duplicate]

This question already has answers here:
Why "Empty do" error when my do isn't empty?
(3 answers)
Closed 2 years ago.
I have editing this code for hours just trying to get rid of this indentation problem and I followed the link I did previously. But because I follow those code I need to readjust again because my spaDatabase and updatedDB is not being recognised which I end up need to readjust everything from the top again and now the bottom part part has problem AGAIN.
I keep deleting and adding space but the error is still there. I also try based on one of the recommended answer I get this parse error below. But if I remove it, it end up being second parse error.
let output :: IO ()
parse error (possibly incorrect indentation or mismatched brackets)
--second error
parse error on input `='
Why "Empty do" error when my do isn't empty?
parse error on input `='
--line of error
output option = case option of
main :: IO()
main = do
contents <- readFile "spa.txt"
let spaDatabase = (read contents :: [Spa])
putStrLn "Please Enter Your Name: "
name <- getLine
putStrLn ("Welcome " ++ name)
putStrLn ""
let menu spaDatabase = do
putStrLn "\nPlease select an option:"
putStrLn "1: Add a new spa to the database "
option <- getLine
output :: IO ()
output option = case option of
1 -> do putStrLn "Enter Spa ID: "
rid <- getLine
let updatedDB = (addSpa rid br ar (read st) spaDatabase)
putStrLn (spaListStr updatedDB)
2 -> putStrLn (spaListStr updatedDB) >> menu spaDB
3 -> do putStrLn "Enter Spa Area:"
ar <- getLine
putStrLn (spaListStr (read ar) spaDatabase)
Here it is with the indents fixed. It's still not right: it defines menu and output but doesn't call them. But it should at least get you past the syntax errors.
main :: IO()
main = do
contents <- readFile "spa.txt"
let spaDatabase = (read contents :: [Spa])
putStrLn "Please Enter Your Name: "
name <- getLine
putStrLn ("Welcome " ++ name)
putStrLn ""
menu spaDatabase = do
putStrLn "\nPlease select an option:"
putStrLn "1: Add a new spa to the database "
getLine -- This returns the value, so no need for <-
output :: Int -> IO ()
output option = case option of
1 -> do
putStrLn "Enter Spa ID: "
rid <- getLine
let updatedDB = (addSpa rid br ar (read st) spaDatabase)
putStrLn (spaListStr updatedDB)
2 -> putStrLn (spaListStr updatedDB) >> menu spaDB
3 -> do
putStrLn "Enter Spa Area:"
ar <- getLine
putStrLn (spaListStr (read ar) spaDatabase)

Messages printed at the wrong moment with putStr

import Control.Monad
import Data.Char
main = forever $ do
putStr "Give me some input: "
l <- getLine
putStrLn $ map toUpper l
I have been learning Haskell from learn you haskell. When i try to run this code it does not behave like it should.
l
Give me some input: L
abc
Give me some input: ABC
When i run this it doesn't print the string first and i can input. After providing some input, in this case l it returns me like this : Give me some input: L.
What it should do is, ask for input by printing Give me some input: and after putting the input it shall return the input in uppercase.
How can i fix this?
As Michail points out, it is a buffering issue, which can be solved with hSetBuffering for stdout:
import Control.Monad
import Data.Char
import System.IO
main = do
hSetBuffering stdout NoBuffering
forever $ do
putStr "Give me some input: "
l <- getLine
putStrLn $ map toUpper l
If for whatever reason you don't want to change the buffer mode for the whole program, you can use hFlush to do an extra flushing of the buffer exactly where you need it:
import Control.Monad
import Data.Char
import System.IO
main = do
forever $ do
putStr "Give me some input: "
hFlush stdout
l <- getLine
putStrLn $ map toUpper l
Try this:
import Control.Monad
import Data.Char
main = forever $ do
putStrLn "Give me some input: "
l <- getLine
putStrLn $ map toUpper l
The issue here is that putStr doesn't write a newline. And the output buffer only gets flushed on a newline.

Haskell print string without newline

When I use this code it's print newline after result. How I can don't write newline?
import System.IO
main :: IO ()
main = do
a <- getLine
b <- getLine
let aa = read a :: Int
let bb = read b :: Int
let cc = aa + bb
print cc
print is defined as putStrLn . show, the fix is to use putStr . show $ cc.
You can also putStr instead of putStrLn. Not sure how you would do something similar with print though.

Haskell hello world won't compile

What is wrong with this code? Trying to do a basic haskell hello world.
module Main
( hello )
where
hello :: [Char] -> [Char]
hello p = "Hello " ++ p ++ "!"
main =
let msg = hello "World"
putStrLn msg
You're missing a do:
main = do
let msg = hello "World"
putStrLn msg
You'll also want to export your main:
module Main ( main ) where
Since this is the main module, there is no need to export hello.
You're missing a in:
main = let msg = hello "World" in putStrLn msg

haskell -skipping getLine

hey - great coders and haskellers,
i'm a haskell freshman and have a problem with a program
it boils down to the following situaition
main :: IO ()
main = do
putStrLn "\nplease give me some input"
input1 <- getLine
putStrLn "\nplease give me another input"
input2 <-getLine
putStrLn ("\nyour inputs were "++show(input1)++" and "++ show(input2)")
putStrLn "restart ?? yY or nN"
c <- getChar
restart c
where
restart c
|elem c "yY" = do
main
|elem c "nN" = putStrLn "\nExample Over"
|otherwise = do
putStrLn "\nyou must type one of Yy to confirm or nN to abort"
c'<- getChar
restart c'
on any but the first execution of main
input1 <- getLine
is skipped and i can find no reason for it, as the following
input2 <- getLine
is executed as expected, i'm open for any suggestions and help
thanks in advance ε/2
The fix: set NoBuffering at the start of your program:
hSetBuffering stdin NoBuffering
Why does this fix the issue? Look at what you're typing when you don't using NoBuffering! You type, and getLine consumes:
first input[enter]
Then you type, and getLine #2 consumes:
second input[enter]
Then you type:
y[enter]
But getChar only consumed the y and leaves the [enter] buffered, which your first getLine call reads! Why did you type [enter]? Because you had to, just hitting 'y' didn't cause main to loop because the terminal was line buffered.

Resources