Haskell:如何在命令行参数中读取int?

时间:2013-08-01 11:41:52

标签: haskell type-conversion

我试图从命令行获取一个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 }

感谢。

3 个答案:

答案 0 :(得分:12)

问题在于优先级:类型签名总是尝试应用于整个表达式(仅使用括号作用域)。因此,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

答案 1 :(得分:10)

您可以封装一个整数命令行参数,如下所示:

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

哪个有效,因为Monads是Functors。或者您可以使用liftM执行相同的操作。

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

main = do
    n <- getIntArg
    disp n

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

答案 2 :(得分:5)

只需删除您在那里添加的显式类型,它就能正常工作。对类型推断有信心。 :)在那里添加print $ ...或类似的东西来纠正新错误。

会发生什么,take的类型是已知的,因此disp期望的参数的类型也是已知的。它是Int。因此,将应用相应的read

少做,做得更多。