0

我正在开发一个供个人使用的家庭作业管理器,使用 Haskell 开发它。作为开始,我制作了以下代码来解析命令行参数,这些代码我以后应该可以通过添加到dispatch. 函数本身是用于测试目的的虚拟对象。然而,我确实觉得这段代码可以变得更简单,更安全,尽管我不知道怎么做。代码是这样的:

module Main where

import System.Environment

main = getArgs >>= parse

parse :: [String] -> IO ()
parse [] = usage
parse (file:mode:[]) = if mode == "list"
                       then list file
                       else case lookup mode dispatch of
                         Just _ -> putStrLn "That mode requires arguments" >> usage
                         Nothing -> putStrLn "Please supply a valid mode" >> usage
parse (file:mode:args) = case lookup mode dispatch of
  Nothing -> do case lookup file dispatch of
                  Just _ -> putStrLn "Please supply a data file"
                  Nothing -> putStrLn "Please supply a valid mode"
                usage
  Just fun -> fun file args
parse (file:[]) = case lookup file dispatch of
  Just _ -> putStrLn "Please supply a datafile" >> usage
  Nothing -> list file

usage :: IO ()
usage = mapM_ putStrLn helptext

helptext :: [String]
helptext = ["Homework manager by Marcus Medom Ryding <mrok4a@gmail.com>"
           ,"Copyright 2013, licensed under BSD3"
           ,"Usage: homework filepath [mode] [arguments]"]

dispatch :: [(String, String -> [String] -> IO ())]
dispatch  = [("new",new)]

new :: String -> [String] -> IO ()
new file args = putStrLn ("NEW: " ++ file) >> mapM_ putStrLn args

list :: String -> IO ()
list file = putStrLn ("LIST: " ++ file)
4

2 回答 2

4

您应该使用库,而不是手动解析命令行。看看cmdargs

它允许您以声明性方式定义命令行选项:

{-# LANGUAGE DeriveDataTypeable #-}

import System.Console.CmdArgs

data MyProg = New {comment :: String}
             | Delete {howMany :: Int}
               deriving (Show, Data, Typeable)

new = New {comment = "this is a parameter with a default value"}
delete = Delete {howMany = 10}

main = print =<< cmdArgs (modes [new, delete])

这给出了类似的东西:

% ./prog new -c "hello world"
New {comment = "hello world"}
% ./prog delete              
Delete {howMany = 10}

您还可以免费获得帮助:

% ./prog --help      
The myprog program

myprog [COMMAND] ... [OPTIONS]

Common flags:
  -? --help          Display help message
  -V --version       Print version information

myprog new [OPTIONS]

  -c --comment=ITEM

myprog delete [OPTIONS]

  -h --howmany=INT

作者也有一个不错的教程。您需要执行类似于“多种模式”部分的操作。

于 2013-04-21T18:39:50.353 回答
1

除了上述答案,仅根据您的代码:

module Main where

import System.Environment

main∷ IO ()
main = getArgs »= parse2

parse2 ∷ [String] → IO ()
parse2 [] = usage
parse2 (file:mode:[])
    | mode ≡ "list" = list file
    | mode ≠ "list" =
    case lookup mode dispatch of
        Just _ → putStrLn "That mode requires arguments" » usage
        Nothing → putStrLn "Please supply a valid mode" » usage
parse2 (file:mode:args) =
    case lookup mode dispatch of
        Nothing → err (lookup file dispatch) » usage
        Just fun → fun file args
        where err (Just _) = putStrLn "Please supply a data file"
              err Nothing = putStrLn "Please supply a valid mode"
parse2 (file:[]) =
    case lookup file dispatch of
        Just _ → putStrLn "Please supply a datafile" » usage
        Nothing → list file

usage ∷ IO ()
usage = mapM_ putStrLn helptext

helptext ∷ [String]
helptext = ["Homework manager by Marcus Medom Ryding <mrok4a@gmail.com>"
           ,"Copyright 2013, licensed under BSD3"
           ,"Usage: homework filepath [mode] [arguments]"]

dispatch ∷ [(String, String → [String] → IO ())]
dispatch  = [("new",new)]

new ∷ String → [String] → IO ()
new file args = putStrLn ("NEW: " ⧺ file) » mapM_ putStrLn args

list ∷ String → IO ()
list file = putStrLn ("LIST: " ⧺ file)
于 2013-04-21T19:23:47.097 回答