Dispatching to correct function with command line arguments in Haskell

前端 未结 1 1267
野性不改
野性不改 2021-01-25 01:36

I\'m writing a little command-line program in Haskell. I need it to dispatch to the correct encryption function based on the command line arguments. I\'ve gotten that far, but t

相关标签:
1条回答
  • 2021-01-25 02:09

    One way is to wrap your functions inside functions that do further command line processing. e.g.

    dispatch::[(String, [String]->IO ())]
    dispatch = [("EEncipher", takesSingleArg ExptCiphers.exptEncipherString)
                ("EDecipher", takesSingleArg ExptCiphers.exptDecipherString)
                ("CEncipher", takesTwoArgs CaesarCiphers.caesarEncipherString)
                ("CDecipher", takesTwoArgs CaesarCiphers.caesarDecipherString)
                ("CBruteForce", takesSingleArg CaesarCiphers.bruteForceCaesar)]
    
    -- a couple of wrapper functions:
    
    takesSingleArg :: (String -> IO ()) -> [String] -> IO ()
    takesSingleArg act [arg] = act arg
    takesSingleArg _   _     = showUsageMessage
    
    takesTwoArgs :: (String -> String -> IO ()) -> [String] -> IO ()
    takesTwoArgs act [arg1, arg2] = act arg1 arg2
    takesTwoArgs _   _            = showUsageMessage
    
    -- put it all together
    
    main = do
        (command:args) <- getArgs
        case lookup command dispatch of
             Just act -> act args
             Nothing  -> showUsageMessage
    

    You can extend this by having variants of the wrapper functions perform error checking, convert (some of) their arguments into Ints / custom datatypes / etc as necessary.

    As dbaupp notes, the way we pattern match on getArgs above isn't safe. A better way is

    run :: [String] -> IO ()
    run [] = showUsageMessage
    run (command : args)
       = case lookup command dispatch of
              Just act -> act args
              Nothing  -> showUsageMessage
    
    main = run =<< getArgs
    
    0 讨论(0)
提交回复
热议问题