Stefan
Stefan

Reputation: 9

Haskell, I need help as I can't seem to work out what I have done wrong. (Basic)

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

Answers (1)

dirkt
dirkt

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

Related Questions