【问题标题】:Command line arguments as Ints in HaskellHaskell 中的命令行参数为 Int
【发布时间】:2021-11-09 13:59:03
【问题描述】:

我有一个 Haskell 程序,它从命令行接受 2 或 3 个 Ints:

-- test.hs

main :: IO ()
main = do
    args <- fmap (read . head) getArgs
    case args of
        [x,y,a] -> doGeneration x y a
        [x,y]   -> doGeneration x y 10
        _       -> usage

但是,当我使用参数运行它时:

$ ./test 100 200
divide: Prelude.read: no parse

为什么?

【问题讨论】:

  • 对于像read这样具有“多态返回类型”的函数,最好使用visible TypeApplications指定要反序列化的类型:read @Int

标签: haskell io monads


【解决方案1】:

getArgs :: IO [String] 返回Strings 的列表,先取头部,然后取args,然后read 该项目。

但是您从未指定它应该读取什么,因为您在 case … of … 子句中使用 args[x,y,a][x, y],它会尝试将其读取为 列表数字(数字的类型由doGeneration 签名指定。这意味着您应该将其写为:

$ ./test <strong>[100,200]</strong>

但我认为这样做没有多大意义,你可以将解析部分重写为:

main :: IO ()
main = do
    args <- fmap (map read) getArgs
    case args of
        [x,y,a] -> doGeneration x y a
        [x,y]   -> doGeneration x y 10
        _       -> usage

这意味着它将单独read每个参数,并用解析的项目构造一个列表,然后我们可以对程序参数的解析部分进行模式匹配。在这种情况下,我们仍然可以使用:

$ ./test <strong>100 200</strong>

【讨论】:

  • 谢谢。它工作得很好,map read 部分对我来说比read . head 更有意义,我实际上在 SO 上发现它是对类似问题的公认答案。
  • “但是您从未指定它应该呈现的内容”是不正确的。目标类型是已知的,而且如果不知道,错误还会谈论“模糊类型”。
  • IO 中,养成使用readIO 而不是read 的习惯可能会更好,就像args &lt;- mapM readIO =&lt;&lt; getArgs 一样。如果有人给出了一个非整数参数,您会立即发现,而不是在第一次强制错误参数时已经完成大量计算之后的某个时间。
【解决方案2】:

你的运行代码相当于

     ....
     case (read "100") of 
         [x,y,a :: Int] -> doGeneration x y a
         [x,y   :: Int] -> doGeneration x y 10
     ....

但是将字符串 "100" 读取为 Ints 的列表是不可能的,也就是“没有解析”。这就是为什么。

Int 来自doGeneration 的签名,您没有包括在内。但它必须是Num,因为您可以互换使用a10

在学习 Haskell 时,最好在 do 块中使用更多变量而不是 fmap。它减轻了认知负担,让您更清楚地看到正在发生的事情:

main :: IO ()
main = do
    args <- getArgs           -- getArgs :: IO [String]
                              -- args    ::    [String]
    let arg1 = head args      -- arg1    ::     String
        val1 = read arg1
    case val1 of
        [x,y,a] -> doGeneration x y a
        [x,y]   -> doGeneration x y 10
        _       -> usage

【讨论】:

  • 我从来没想过read 会在这里期待[Int]。谢谢!
猜你喜欢
  • 2012-01-26
  • 2020-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-27
相关资源
最近更新 更多