10

我正在尝试从命令行获取一个 int 值并将其传递给disp函数。

import System(getArgs)

main = do
    args <- getArgs
    disp $ read $ head args :: Int

disp n = take n $ repeat 'S'

ghc 给出的错误是

 Couldn't match expected type `Int' with actual type `[Char]'
 In the expression: disp $ read $ head args :: Int
 In the expression:
   do { args <- getArgs;
            disp $ read $ head args :: Int }
 In an equation for `main':
     main
       = do { args <- getArgs;
                  disp $ read $ head args :: Int }

谢谢。

4

3 回答 3

13

问题在于优先级:类型签名总是试图应用于整个表达式(仅使用括号限定范围)。所以你的disp $ read $ head args :: Int解析为(disp $ read $ head args) :: Int,这显然是不正确的。您可以像这样使用括号:

disp (read $ head args :: Int)

或者省略类型签名,因为 GHC 在这种情况下可以推断它:

disp $ read $ head args

这段代码仍然不能按原样工作,因为你在 IO monad 中,所以你需要产生 IO 动作。您可以通过打印结果来做到这一点,例如:

putStrLn $ disp $ read $ head args
于 2013-08-01T11:55:09.847 回答
11

您可以像这样封装拉取整数命令行参数:

getIntArg :: IO Int
getIntArg = fmap (read . head) getArgs

之所以有效,是因为 Monad 是 Functor。或者你可以用liftM.

这样你的main功能就变成了:

main = do
    n <- getIntArg
    disp n

前提是您添加了某种类型的打印功能,disp如其他答案中所述。

于 2013-08-01T14:14:11.147 回答
5

只需删除您在此处添加的显式类型,它就会起作用。相信类型推断。:) 添加print $ ...那里,或类似的东西,以纠正新的错误。

发生的情况是,类型take是已知的,因此disp期望的参数类型也是已知的。它是Int。因此read将应用适当的。

少做,多做。

于 2013-08-01T11:53:23.853 回答