以下程序有什么问题?

时间:2011-04-28 10:19:28

标签: haskell

这段代码出了什么问题?

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

以下是错误消息:

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'

2 个答案:

答案 0 :(得分:8)

read args !! 0应为read (args !! 0)add x y = x +应为add x y = x + y。此外putStrLn仅使用字符串,因此请使用print代替字符串。


然而,看到你是哈斯凯尔的新手。我重新编写了你的​​部分程序,以展示更加有问题的方式。

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

我觉得现在看起来有点干净了。请注意,使用!!通常被视为不良做法。

答案 1 :(得分:3)

只是为错误消息和给出的解决方案添加一些细节。看第一个错误:

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

这可能有点不清楚。看看putStrLn的类型签名:

putStrLn :: String -> IO ()

因此,putStrLn是一个接受String并计算IO动作的函数。但是你直接试图传递putStrLn一些表达式,如(x + y),这是一个数字,而字符串不是数字(在Haskell术语中,它的类型签名是(Num t)=&gt;吨)。

上面给出的解决方案建议使用打印功能:

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

'print'和'putStrLn'之间的区别在于打印可以显示任何可显示的内容,其中包括数字。

接下来:

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

这说编译器期望String作为第一个读取的参数,但是看到了一个字符串列表。看原始代码:

read args !! 0

在Haskell中,函数应用程序具有最高优先级,因此编译器基本上读取您的代码:

(read args) !! 0

(特别注意读取的应用程序绑定高于使用!!运算符)。希望现在应该清楚读取已应用于所有args

由于您的意图似乎是阅读args的第一个元素,您需要使用如下括号:

read (args !! 0)

希望这会使错误消息更容易理解!