Reputation: 9
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
Upvotes: 0
Views: 105
Reputation: 473
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
Upvotes: 3