Basic error with `putStrLn` in Haskell. VScode extension Haskelly [duplicate] - haskell

This question already has answers here:
A mystery involving putStrLn
(2 answers)
Closed 3 years ago.
main = do line <- getLine
let line' = reverse line
putStrLn $ "You said " ++ line' ++ " backwards!"
putStrLn $ "Yes, you really said " ++ line ++ " backwards!"
Error:
$ stack runhaskell "c:\Users\FruitfulApproach\Desktop\Haskell\test.hs"
C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:4:5: error:
parse error on input `putStrLn'
|
4 | putStrLn $ "You said " ++ line' ++ " backwards!"
| ^^^^^^^^
I've also tried it with a single tab on the indented lines.
Here's my tabs -> spaces setting:
I've also tried restarting VSCode.
Thanks in advance!

I believe your code is insufficiently indented. Try this:
main = do line <- getLine
let line' = reverse line
putStrLn $ "You said " ++ line' ++ " backwards!"
putStrLn $ "Yes, you really said " ++ line ++ " backwards!"
Specifically, your lines following the do should be indented just as much as the thing that comes after it, namely line <- getLine.

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)

A mystery involving putStrLn

Why does the piece of code below produce the error parse error on input ‘putStrLn’?
main = do line <- fmap reverse getLine
putStrLn $ "You said " ++ line ++ " backwards!"
putStrLn $ "Yes, you said " ++ line ++ " backwards!"
<interactive>:11:4: error: parse error on input ‘putStrLn’
Also, why does the following piece of code produce the error parse error on input ‘let’?
main = do line <- getLine
let line' = reverse line
putStrLn $ "You said " ++ line' ++ " backwards!"
putStrLn $ "Yes, you said " ++ line' ++ " backwards!"
<interactive>:31:4: error: parse error on input ‘let’
Both snippets have the same problem. If you put the first action of a do block on the same line as the do itself, you still have to indent the rest of the actions in the do block as far as the first one. Two choices to fix it:
main = do line <- fmap reverse getLine
putStrLn $ "You said " ++ line ++ " backwards!"
putStrLn $ "Yes, you said " ++ line ++ " backwards!"
or
main = do
line <- fmap reverse getLine
putStrLn $ "You said " ++ line ++ " backwards!"
putStrLn $ "Yes, you said " ++ line ++ " backwards!"
It also works when explicit separators are used throughout:
main = do { line <- fmap reverse getLine ;
putStrLn $ "You said " ++ line ++ " backwards!" ;
putStrLn $ "Yes, you said " ++ line ++ " backwards!" }
main = do { line <- getLine ;
let { line' = reverse line } ; -- NB let's { }s
putStrLn $ "You said " ++ line' ++ " backwards!" ;
putStrLn $ "Yes, you said " ++ line' ++ " backwards!" }
This is not a substitute for the good indentation style, but an addition to it.

How do I show two inputs are the same or not

I'm trying to just compare two user inputs but I can't seem to get it working and constantly get parse errors. Any help will be appreciated.
main = do
foo <- putStrLn "Enter two numbers."
numone <- getLine
numtwo <- getLine
putStrLn $ ("You entered " ++ numone ++ " and " ++ numtwo)
if
numone == numtwo
then
putStrLn "They are the same"
else
putStrLn "They are not the same"
The errors probably arise through to small changes in indentation between the local version, and the one posted here. Indentation in Haskell is quite important, since the compiler uses it to understand where certain "blocks" begin and end.
Furthermore you can remove the foo <- part (well this is not wrong, but quite useless). So after reformatting we get:
main = do
putStrLn "Enter two numbers."
numone <- getLine
numtwo <- getLine
putStrLn $ ("You entered " ++ numone ++ " and " ++ numtwo)
if numone == numtwo
then
putStrLn "They are the same"
else
putStrLn "They are not the same"
Furthermore now you compare two strings. You can convert these to Ints (or other readable types) with for example readLn :: Read a => IO a:
main = do
putStrLn "Enter two numbers."
numone <- readLn :: IO Int
numtwo <- readLn :: IO Int
putStrLn $ ("You entered " ++ show numone ++ " and " ++ show numtwo)
if numone == numtwo
then
putStrLn "They are the same"
else
putStrLn "They are not the same"
You have mixed tabs and spaces in your code snippet, and the blank line in between your print and your if expression is indented by less than the other lines are. Your whole do-block must have the same initial indentation. I suggest using only spaces (or only tabs, if you prefer) so that it's harder to accidentally wind up with misaligned code that looks correctly aligned.
I see I answered on the basis of code OP never wrote, because of an incorrect edit someone else made. It "fixed" the indentation but was actually still wrong for a different reason. Oh well, it's still an indentation problem but not one to do with mixing spaces and tabs.

Haskell desugar syntax

Shuklan's Haskell Lecture wanted the following code desugared:
main = do
putStrLn "Enter name:"
name <- getLine
putStrLn ("Hi " ++ name)
I came up with:
main = putStrLn "Enter name:" >> getLine >>= \str -> putStrLn ("Hi " ++ str)
He revealed:
main = putStrLn "Enter name:" >> getLine >>= putStrLn . ("Hi " ++)
Never seen that syntax before, how does it work?
The snippets are identical, the latter just uses point free style (also punningly referred to as "pointless style").
The central point is that ("Hi " ++) is a partially applied (++) that prepends "Hi " to the input.
This function is composed (using .) with putStrLn to get a function that prepends "Hi " to the input and then prints it.
This is exactly what your more explicit lambda does.

Haskell new line not working

Been messing around for about 20 minutes now trying to get the new line working however it always shows in GHCI as a single line.
Here is what I enter into GHCi:
displayFilm ("Skyfall",["Daniel Craig", "Judi Dench", "Ralph Fiennes"], 2012, ["Bill", "Olga", "Zoe", "Paula", "Megan", "Sam", "Wally"])
Here is what is printed:
"Skyfall----------\n Cast: Daniel Craig, Judi Dench, Ralph Fiennes\n Year: 2012\n Fans: 7\n"
displayList :: [String] -> String
displayList [] = ""
displayList [x] = x ++ "" ++ displayList []
displayList (x:xs) = x ++ ", " ++ displayList xs
displayFilm :: Film -> String
displayFilm (title, cast, year, fans) =
title ++ "----------" ++
"\n Cast: " ++ (displayList cast) ++
"\n Year: " ++ (show year) ++
"\n Fans: " ++ show (length fans) ++ "\n"
To print a string as it is, without escaping special characters, use:
putStr string
or
putStrLn string
if you want an extra newline at the end. In you case, you are probably looking for
putStr (displayFilm (....))
Why is this needed? In GHCi, if you evaluate an expression s the result will be printed as if running print s (unless it has type IO something -- forget about this special case). If e is a string, print escapes all the special characters and output the result. This is because print is meant to output a string whose syntax follows the one in Haskell expressions. For numbers, this is the usual decimal notation. For strings, we get quotes and escaped characters.
When you type an expression into GHC, it displays it using print. Calling print on a string shows its content but does not evaluate escape sequences:
> print "line1\nline"
"line1\nline2"
Note the quotes.
To display the string as you desire, use putStr or putStrLn (the latter will append a newline).
> putStr "line1\nline2"
line1
line2

Resources