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

10 haskell type-conversion

我试图从命令行获取一个int值并将其传递给该disp函数.

import System(getArgs)

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

disp n = take n $ repeat 'S'
Run Code Online (Sandbox Code Playgroud)

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 }
Run Code Online (Sandbox Code Playgroud)

谢谢.

ben*_*ofs 12

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

disp (read $ head args :: Int)
Run Code Online (Sandbox Code Playgroud)

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

disp $ read $ head args
Run Code Online (Sandbox Code Playgroud)

此代码仍然无法正常工作,因为您处于IO monad中,因此您需要生成IO操作.您可以通过打印结果来执行此操作,例如:

putStrLn $ disp $ read $ head args
Run Code Online (Sandbox Code Playgroud)

  • @kadaj IO-do-block中的所有语句都必须返回IO操作.但是,您可以使用let分配可以是任何类型的变量:`let myDispResult = disp $ read $ head args`. (2认同)
  • 您不必生成输出,但必须创建IO操作.如果要返回计算值,可以使用`return`,它将值包装在IO monad中.也就是说,`main`的类型必须是`IO()`,而不是`IO String`,因此在这种情况下不会起作用. (2认同)

小智 11

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

getIntArg :: IO Int
getIntArg = fmap (read . head) getArgs
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为Monads是Functors.或者你也可以做同样的事情liftM.

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

main = do
    n <- getIntArg
    disp n
Run Code Online (Sandbox Code Playgroud)

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


Wil*_*ess 5

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

会发生什么,take已知的类型,所以disp预期的参数类型也是已知的.是的Int.因此适用read将适用.

做得少,做得更多.

  • 但是`disp`产生一个`String`,所以你可能想添加`putStrLn`. (2认同)