Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
122 views
in Technique[技术] by (71.8m points)

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
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...