2012-04-07 71 views
1

这是一个扩展到这个问题的东西:我需要哪个Monad?

Dispatching to correct function with command line arguments in Haskell

所以,事实证明,我没有一个很好的解决方案还为在命令行中的其他功能调度“命令”。所以,我想在上面的问题中扩展这个方法。手动添加函数到表中并将适当的转换函数应用于每个函数似乎很麻烦,因此它需要一个正确大小的列表而不是正常参数。相反,我想建一个表,我会用它需要在命令行采取的参数个数增加功能和“标签”他们。 “添加”的过程,应该然后采取与正确的“takesXarguments”程序组成并将其添加到表的照顾。

我希望能够在表中安装函数的“包”,这让我认为我需要能够跟踪表的状态,因为它会在安装包时发生变化。读者Monad或国家Monad是我在找什么?

回答

1

没有必要的单子。您的标记理念是正确的,但这些信息的编码方式可能与预期不同。

我将开始与命令的定义:

type Command = [String] -> IO() 

然后你就可以“指挥机”功能:

mkCommand1 :: (String -> IO()) -> Command 
mkCommand2 :: (String -> String -> IO()) -> Command 
... 

用作标签。如果你不喜欢的功能的扩散,你也可以做一个“命令拉姆达”:

arg :: (String -> Command) -> Command 
arg f (x:xs) = f x xs 
arg f [] = fail "Wrong number of arguments" 

所以,你可以写这样的命令:

printHelloName :: Command 
printHelloName = arg $ \first -> arg $ \last -> do 
    putStrLn $ "Hello, Mr(s). " ++ last 
    putStrLn $ "May I call you " ++ first ++ "?" 

当然mkCommand1等可很容易写在arg方面,为了两全其美。

至于包,Command足够封装多个子命令之间的选择,但它们不构成。这里的一个选项是改变Command到:

type Command = [String] -> Maybe (IO()) 

,它允许你通过采取不返回Nothing的第一个动作组成多个Command s转换为一个。现在你的软件包只是Command的值。 (通常对于Haskell,我们对这些组合非常感兴趣 - 而不是包和列表,请考虑如何将两个对象构成一个复合对象)

为了让您免于您已经建立的愿望(1)没有合理的方法来检测一个函数所需的参数数*,并且(2)没有办法使一个类型取决于一个数字,所以你将不能创建一个mkCommand它将参数个数作为第一个参数Int

希望这有助于。

  • 在这种情况下,事实证明存在这种情况,但我建议不要这样做,并认为这是一种坏习惯 - 当事情变得更抽象时,技术就会崩溃。但我是纯粹主义者;哈斯克勒斯可能会不同意我的观点。
+0

我只是希望我有Haskell技能,能够成为一个纯粹哈哈。你认为你可以详细说明该功能如何作为标签吗?或者该类型用作标签。我仍然困惑。顺便说一句,这不是一个家庭作业问题或任何事情。这只是一个我帮助我学习的小型Haskell项目。 – 2012-04-07 22:00:21