Haskell:如何将命令行参数读取为整数?

10

我正在尝试从命令行获取一个整数值,并将其传递给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 }

感谢您的选择。

你需要使用 read :: (Read a) => [Char] -> a 来将参数解析为 int (Int 是 Read 的实例)。 - bennofs
我在上面使用了 read。从 Prelude 中使用 read 是可以的。例如:take (read $ head ["5", "4", "3"] ::Int) [x | x <- [1..19]] 可以正常工作,输出 [1,2,3,4,5] - user235273
1
把你添加的 :: Int 删掉就可以了。它会自动识别使用哪个 read 函数。 - Will Ness
我遇到了错误:期望的类型是 IO b0',但实际类型是 [Char]'。 - user235273
2
那是因为你需要在那里添加 printprint $ disp ... - Will Ness
3
هڈ¯ن»¥ن½؟用replicate n 'S'ن»£و›؟take n $ repeat 'S'م€‚ - amindfv
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

是的,这个方法可行!">你正在IO单子中,所以你需要生成IO操作。"我正在IO单子中获取输入,是否必须生成IO输出而不仅仅是返回不属于IO类型的值?作为Haskell新手,我应该阅读更多关于IO的内容,但对此有任何想法也会很有帮助。 - user235273
2
@kadaj 在 IO-do 块中的所有语句都必须返回 IO 操作。但是,您可以使用 let 分配任何类型的变量:let myDispResult = disp $ read $ head args - bennofs
2
你不必生成输出,但必须创建一个IO操作。如果想要返回计算出的值,可以使用return,它将该值包装在IO单子中。话虽如此,main的类型必须是IO(),而不是IO String,所以在这种情况下无法使用。 - sepp2k

11

您可以这样封装从命令行提取整数参数的过程:

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

这是行得通的,因为单子也是函子。或者您可以使用 liftM 来完成相同的事情。

这样,您的 main 函数就变成了:

main = do
    n <- getIntArg
    disp n

在讨论的其他答案中提到,只要您添加某种打印函数到disp中即可。


5

只需删除您添加的显式类型,它就能正常工作。相信类型推断。 :) 在那里添加print $ ...或类似的内容,以更正新错误。

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

做得少,完成得更多。


2
但是disp生成的是一个String,所以你可能想要添加putStrLn - kosmikus
1
@kosmikus或打印。但这与被问到的无关。 - Will Ness
我指出这个问题是因为你说“它会工作”,如果存在独立的类型错误,这是具有误导性的。但是,print当然也可以工作。 - kosmikus
@kosmikus 我所指的“it”并不是你所想的“it”。 :) 我所说的“it”代表着“尝试从命令行获取一个int值并将其传递给disp函数”,正如问题所问。 - Will Ness

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接