【发布时间】:2012-05-28 15:22:38
【问题描述】:
我正在尝试自学 Haskell。作为一个示例程序,我正在编写一个蜘蛛纸牌播放器。
我正在尝试使用System.Console.GetOpt 编写命令行解析器。我知道有更简单的方法可以对这个程序进行参数解析,但我想学习如何使用 GetOpt 模块,因为我预计稍后在我将要编写的其他程序中需要它的复杂性。
我正在尝试添加一个“--help”选项,它只打印一条使用消息然后退出。如果“--games”选项或“--suits”选项的任何一个参数不是有效整数(游戏> = 1和Options 数据类型传递给我程序的其他部分。
我还收到progName 不在范围内的错误。 parseArgs中的case语句不是在do块的范围内吗?
这是我的代码,由"Real World Haskell" 和Haskell wiki 中的示例拼凑而成:
module Main (main) where
import System.Console.GetOpt
import System.Environment(getArgs, getProgName)
data Options = Options {
optGames :: Int
, optSuits :: Int
, optVerbose :: Bool
} deriving Show
defaultOptions = Options {
optGames = 1
, optSuits = 4
, optVerbose = False
}
options :: [OptDescr (Options -> Options)]
options =
[ Option ['g'] ["games"]
(ReqArg (\g opts -> opts { optGames = (read g) }) "GAMES")
"number of games"
, Option ['s'] ["suits"]
(ReqArg (\s opts -> opts { optSuits = (read s) }) "SUITS")
"number of suits"
, Option ['v'] ["verbose"]
(NoArg (\opts -> opts { optVerbose = True }))
"verbose output"
]
parseArgs :: IO Options
parseArgs = do
argv <- getArgs
progName <- getProgName
case getOpt RequireOrder options argv of
(opts, [], []) -> return (foldl (flip id) defaultOptions opts)
(_, _, errs) -> ioError (userError (concat errs ++ helpMessage))
where
header = "Usage: " ++ progName ++ " [OPTION...]"
helpMessage = usageInfo header options
main :: IO ()
main = do
options <- parseArgs
putStrLn $ show options
【问题讨论】:
-
作用域是因为
where子句附加到parseArgs,其中progName不在作用域内(它绑定在do 块中)。如果您将where缩进一点,它就会附加到case,并且progName在范围内。 -
(如果有“为什么会出现这个错误”以外的问题,您应该明确说明该问题。)
-
谢谢。我缩进了
whereclause,直到它比第二种情况((_, _, errs))多一个缩进级别并且它起作用了,但是我假设值header和helpMessage将不在第一种情况的范围内条款。我将它们向上移动到do块的let值,并删除了where。