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.
Related
I'm new to Haskell and am trying to learn using things like learn you a Haskell. Can someone explain what is wrong with my code as I don't really know how to read error messages yet. All I can tell so far is that the let statements aren't correct but I need them to work somehow because without them the (show (typeOf numone/numtwo)) only shows the type of either 'numone' or 'numtwo' and not the inputted values from the getLine.
What I am trying to do is compare the inputs and show the types of the inputs but this is as far I can go without some help.
import Data.Typeable
main = do
putStrLn "Enter two statements."
numone <- getLine
numtwo <- getLine
putStrLn $ ("You entered " ++ show numone ++ (show (typeOf numone)) ++ " and " ++ show numone ++ (show (typeOf numone)))
let numone = getLine
let numtwo = getLine
if numone == numtwo
then
putStrLn $ "They are the same and their types are " ++ (show (typeOf numone)) ++ " and " ++ (show (typeOf numtwo))
else
putStrLn $ "They are not the same"
Error message;
• No instance for (Eq (IO String)) arising from a use of ‘==’
• In the expression: numone == numtwo
In a stmt of a 'do' block:
if numone == numtwo then
putStrLn
$ "They are the same and their types are "
++ (show (typeOf numone)) ++ " and " ++ (show (typeOf numtwo))
else
putStrLn $ "They are not the same"
In the expression:
do putStrLn "Enter two statements."
numone <- getLine
numtwo <- getLine
putStrLn
$ ("You entered "
++
show numone
++
(show (typeOf numone))
++ " and " ++ show numone ++ (show (typeOf numone)))
....
|
10 | if numone == numtwo
| ^^^^^^^^^^^^^^^^
The output should be something like (depending on the input of getLine);
> You entered A123[String] and B456[String]
> They are the same and their types are [String] and [String]
or
They are not the same
If your code is exactly as shown in the question, then the first problem is indentation.
Indentation matters in Haskell (like in Python), unless you use the { ... ; ... ; ... } syntax.
The second problem is that getLine is an action in the IO-monad, so you can't use let, but must use a monadic binding.
Oh, and the second binding overrides the first. So while using the name a second time is not wrong, it's bad style.
The third thing (it's not really a problem) is that the code as written will assign static types to numone and numtwo - it's not somehow like entering different values will change their type. getLine has type
getLine :: IO String
so you'll always see [Char] (aka String) as the type.
The fourth problem is that you used numone twice in the first output, instead of numone and numtwo.
Edit
I completely removed the second input (the former let-statements) according to the comments.
Here's the corrected program:
import Data.Typeable
main :: IO ()
main = do
putStrLn "Enter two statements."
numone <- getLine
numtwo <- getLine
putStrLn $ ("You entered " ++ show numone ++ (show (typeOf numone)) ++ " and " ++ show numtwo ++ (show (typeOf numtwo)))
if numone == numtwo then
putStrLn $ "They are the same and their types are " ++ (show (typeOf numone)) ++ " and " ++ (show (typeOf numtwo))
else
putStrLn $ "They are not the same"
return ()
Example session fro ghci:
*Main> main
Enter two statements.
A123
B456
You entered "A123"[Char] and "B456"[Char]
They are not the same
*Main> main
Enter two statements.
A123
A123
You entered "A123"[Char] and "A123"[Char]
They are the same and their types are [Char] and [Char]
*Main>
So that should do what you want.
Let me emphasize again: You'll always get [Char] as the type, no matter what you do. You can't assign dynamic types based on input. And in general, the Haskell typesystem is static; while there are some advanced constructions like Data.Typeable, I wouldn't recommend them for beginners. Your mental image should be "when I compile the program, the Haskell typechecker will assign a single static type to every subexpression". You can actually ask the typechecker for those by using :t in the REPL:
*Main> :t getLine
getLine :: IO String
How can I use a variable scoped in the Bool section of whileM_ later in its body?
For example:
guess :: IO ()
guess = do
putStrLn "Please input your guess."
whileM_
(do
guess <- getLine
return (guess /= "secret"))
(do
putStrLn ("You guessed: " ++ guess)
putStrLn ("And " ++ guess ++ " is wrong."))
putStrLn "Right - Bye..."
guess is not in scope in the second do block so unavailable for use.
How can I bring it into scope?
Thank you.
whileM_ doesn't have a built-in way of achieving this. That combinator is really a bit limiting; as dfeuer says you should probably just write the loop yourself using recursion. Or, use the loop construct that actually has support for this kind of information transfer:
guess :: IO ()
guess = do
putStrLn "Please input your guess."
whileJust_
(do
lastGuess <- getLine -- don't use the name `guess` if that's already a global function name!
return $ if lastGuess /= "secret"
them Just lastGuess else Nothing )
(\lastGuess -> do
putStrLn $ "You guessed: " ++ lastGuess
putStrLn $ "And " ++ lastGuess ++ " is wrong." )
putStrLn "Right - Bye..."
However you can also communicate values between the condition- and execution parts of whileM_. Two options:
Specifically in IO, you can always use IORefs.
guess :: IO ()
guess = do
putStrLn "Please input your guess."
bestGuess <- newIORef ""
whileM_
(do lastGuess <- getLine
writeIORef bestGuess lastGuess
return $ lastGuess /= "secret" )
(do lastGuess <- readIORef bestGuess
putStrLn $ "You guessed: " ++ lastGuess
putStrLn $ "And " ++ lasyGuess ++ " is wrong." )
putStrLn "Right - Bye..."
This is rather eschewed in Haskell – an IORef is basically a mutable variable – but sometimes it's sensible. Definitely not a good idea here.
You can instead of IO use a dedicated monad with a pure-functional state variable. That requires a monad transformer. It's a slightly advanced technique, but for complex application can work out extremely well.
I'm new to Haskell and would be glad if someone would be willing to help me! I'm trying to get this program to work with a do while loop.
The result from the second getLine command gets put into the varible goGlenn and if goGlenn doesn't equal "start" then the program will return to the beginning
start = do
loop $ do lift performAction
putStrLn "Hello, what is your name?"
name <- getLine
putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.")
putStrLn "You will receive fifty questions in total to which you can reply with Yes or No."
putStrLn "Whenever you feel ready to begin please write Start"
goGlenn <- getLine
putStrLn goGlenn
while (goGlenn /= "start")
In Haskell you write "loops" recursively, most of the times.
import Control.Monad
-- ....
start = do
putStrLn "Before the loop!"
-- we define "loop" as a recursive IO action
let loop = do
putStrLn "Hello, what is your name?"
name <- getLine
putStrLn $ "Welcome to our personality test " ++ name
++ ", inspired by the Big Five Theory."
putStrLn "You will receive fifty questions in total to which you can reply with Yes or No."
putStrLn "Whenever you feel ready to begin please write Start"
goGlenn <- getLine
putStrLn goGlenn
-- if we did not finish, start another loop
when (goGlenn /= "start") loop
loop -- start the first iteration
putStrLn "After the loop!"
Not sure, maybe this version can helps you:
import Control.Monad
loop action = do
condition <- action
when condition (loop action)
while = return
start =
let action = do {
putStrLn "Hello, what is your name?";
name <- getLine;
putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.");
putStrLn "You will receive fifty questions in total to which you can reply with Yes or No.";
putStrLn "Whenever you feel ready to begin please write Start";
goGlenn <- getLine;
putStrLn goGlenn;
while (goGlenn /= "start");
}
in loop action
(Edit) or can be too:
start =
loop (do {
putStrLn "Hello, what is your name?";
name <- getLine;
putStrLn ("Welcome to our personality test " ++ name ++ ", inspired by the Big Five Theory.");
putStrLn "You will receive fifty questions in total to which you can reply with Yes or No.";
putStrLn "Whenever you feel ready to begin please write Start";
goGlenn <- getLine;
putStrLn goGlenn;
while (goGlenn /= "start");
})
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.
I am trying to make a program that reads a number given by a user and then prints it. the number has to be an integer when I print it, but this code gives me a parse error:
main = do
{
putStrLn "Please enter the number"
number <- getLine
putStrLn "The num is:" ++ show (read number:: Int)
}
If you use brackets in your do statement, you have to use semicolons. Also, the last line should be putStrLn $ "The num is:" ++ show (read number :: Int)
So you have two options:
main = do
{
putStrLn "Please enter the number";
number <- getLine;
putStrLn $ "The num is:" ++ show (read number:: Int)
}
or:
main = do
putStrLn "Please enter the number"
number <- getLine
putStrLn $ "The num is:" ++ show (read number:: Int)
Almost all of the code I've seen uses the second version, but they are both valid. Note that in the second version, whitespace becomes significant.
Haskell recognizes the Tab character and your program could be failing because of that. If you're using Tabs, change them to whitespaces.