使用Haskell中的命令行参数调度以纠正函数 [英] Dispatching to correct function with command line arguments in Haskell

查看:126
本文介绍了使用Haskell中的命令行参数调度以纠正函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Haskell编写了一个小命令行程序。我需要它根据命令行参数分派到正确的加密函数。我已经得到了那么多,但是我需要剩下的参数作为参数传递给函数。我读过:



http:// learnyouahaskell .com / input-and-output



这让我感觉如此:

 导入合格的CaesarCiphers 
导入合格的ExptCiphers

dispatch :: [(String,String-> IO())]
dispatch = [( (CEncipher,CaesarCiphers.caesarEncipherString),
(CDecipher,CaesarCiphers.caesarDecipherString)
(EDecipher,ExptCiphers.exptDecipherString)
(CEncipher,ExifCiphers.exptEncipherString) (CBruteForce,CaesarCiphers.bruteForceCaesar)]

main = do
(command:args)< - getArgs

每个函数都有一些我不知道直到运行时间的参数。如何将这些函数传递给一个函数,看看它们将被绑定在一个列表中?我只是手动抓住他们?例如:

  exampleFunction(args !! 1)(args !! 2)

这看起来很丑陋。是否有某种惯用的方式来做到这一点?那错误检查呢?我的功能没有装备来优雅地处理错误,例如在白痴命令中传递参数。

另外,重要的是,每个调度函数都有不同数量的参数,所以我无法静态地执行此操作(如上所述)。这太糟糕了 unCurry command args 是无效的Haskell。

解决方案

你的函数在进行进一步命令行处理的函数中。例如

  dispatch :: [(String,[String]  - > IO())] 
dispatch = [ (EEncipher,采取SingleArg ExptCiphers.exptEncipherString)
(EDecipher,takesSingleArg ExptCiphers.exptDecipherString)
(CEncipher,takesTwoArgs CaesarCiphers.caesarEncipherString)
(CDecipher,takeTwoArgs CaesarCiphers。 caesarDecipherString)
(CBruteForce,takesSingleArg CaesarCiphers.bruteForceCaesar)]

- 一对包装函数:

takesSingleArg ::(String - > IO ()) - > [字符串] - > IO()
takesSingleArg act [arg] = act arg
takesSingleArg _ _ = showUsageMes​​sage

takesTwoArgs ::(String - > String - > IO()) - > ; [字符串] - > IO()
takesTwoArgs act [arg1,arg2] = act arg1 arg2
takesTwoArgs _ _ = showUsageMes​​sage

- 放在一起

main = do
(command:args)< - getArgs
大小写查找命令
的发送只需执行 - > act args
Nothing - > showUsageMes​​sage

您可以通过使包装函数的变体执行错误检查,它们的参数转换为 Int s /自定义数据类型/ etc。



dbaupp注意到,上面的 getArgs 不安全。更好的方法是:

  run :: [String]  - > IO()
run [] = showUsageMes​​sage
run(command:args)
= case查询命令
的分派只需要执行 - > act args
Nothing - > showUsageMes​​sage

main = run =<< getArgs


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 then I need the remaining arguments to get passed to the function as parameters. I've read:

http://learnyouahaskell.com/input-and-output

That's gotten me this far:

import qualified CaesarCiphers
import qualified ExptCiphers

dispatch::[(String, String->IO ())]
dispatch = [("EEncipher", ExptCiphers.exptEncipherString)
            ("EDecipher", ExptCiphers.exptDecipherString)
            ("CEncipher", CaesarCiphers.caesarEncipherString)
            ("CDecipher", CaesarCiphers.caesarDecipherString)
            ("CBruteForce", CaesarCiphers.bruteForceCaesar)]

main = do
    (command:args) <- getArgs

Each of the functions takes some arguments that I won't know untill run-time. How do I pass those into a function seeing as they'll be bound up in a list? Do I just grab them manually? Like:

exampleFunction (args !! 1) (args !! 2) 

That seems kind of ugly. Is there some sort of idiomatic way to do this? And what about error checking? My functions aren't equipped to gracefully handle errors like getting passed parameters in an idiotic order.

Also, and importantly, each function in dispatch takes a different number of arguments, so I can't do this statically anyways (as above.) It's too bad unCurry command args isn't valid Haskell.

解决方案

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

这篇关于使用Haskell中的命令行参数调度以纠正函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆