Luke
Luke

Reputation: 5971

What's wrong with the following program?

what's wrong with this code?

module Main where
import System.Environment
main :: IO ()
main = do
    args <- getArgs
    putStrLn ("Hello, " ++ args !! 0 ++ ", " ++ args !! 1)
    putStrLn(add (read args !! 0) (read args !! 1))
add x y = x + y

Here are the error messages:

main.hs:8:15:
    No instance for (Num String)
      arising from a use of `add'
    Possible fix: add an instance declaration for (Num String)
    In the first argument of `putStrLn', namely
      `(add (read args !! 0) (read args !! 1))'
    In the expression: putStrLn (add (read args !! 0) (read args !! 1))
    In the expression:
      do { args <- getArgs;
           putStrLn ("Hello, " ++ args !! 0 ++ ", " ++ args !! 1);
           putStrLn (add (read args !! 0) (read args !! 1)) }

main.hs:8:25:
    Couldn't match expected type `Char' with actual type `[Char]'
    Expected type: String
      Actual type: [String]
    In the first argument of `read', namely `args'
    In the first argument of `(!!)', namely `read args'

Upvotes: 0

Views: 1078

Answers (2)

monk
monk

Reputation: 981

Just to add a little elaboration on the error messages and the solution given. Looking at the first error:

    No instance for (Num String)
    ...
    In the first argument of `putStrLn'

This might be a bit unclear. Have a look at the type signature for putStrLn:

putStrLn :: String -> IO ()

So, putStrLn is a function that takes a String and evaluates to an IO action. However you have directly tried to pass putStrLn some expression like (x + y), which is a number, and Strings are not numbers (in Haskell terms, its type signature is (Num t) => t).

The solution given above suggests using the print function instead:

print :: (Show a) => a -> IO ()

The difference between 'print' and 'putStrLn' is that print can take anything showable, which includes numbers.

Next up:

    Couldn't match expected type `Char' with actual type `[Char]'
    Expected type: String
      Actual type: [String]
    In the first argument of `read', namely `args'

This says the compiler expected a String as the first argument to read, but saw a list of Strings. Looking at the original code:

read args !! 0

In Haskell, function application has highest precedence, so the compiler basically reads your code like so:

(read args) !! 0

(note in particular that the application of read binds higher than the use of the !! operator). Hopefully it should be clear now that read has been applied to all of args.

As your intention seemed to be to read the first element of args, you need to use parentheses like so:

read (args !! 0)

Hope this makes the error messages a little more understandable!

Upvotes: 3

Tarrasch
Tarrasch

Reputation: 10547

read args !! 0 should be read (args !! 0) and add x y = x + should be add x y = x + y. Also putStrLn takes a string only, so use print instead which also prints numbers.


However, seeing you are new to haskell. I rewrote part of your program to demonstrate a more haskellish way.

main = do
    (arg0:arg1:restArgs) <- getArgs
    putStrLn $ "Hello, " ++ arg0 ++ ", " ++ arg1
    print $ add (read arg0) (read arg1)
add = (+)

I think it looks a bit cleaner now. Note that it's most often considered bad practice to use !!.

Upvotes: 8

Related Questions