1

这是对这个问题的扩展:

在 Haskell 中使用命令行参数调度以纠正函数

所以,事实证明,我还没有一个很好的解决方案来将“命令”从命令行分派到其他函数。因此,我想扩展上述问题中的方法。必须手动将函数添加到表中并将适当的转换函数应用于每个函数,以便它获取正确大小的列表而不是其正常参数,这似乎很麻烦。相反,我想建立一个表,我将在其中添加函数并用它需要从命令行获取的参数数量“标记”它们。然后,“add”过程应负责使用正确的“takesXarguments”过程进行组合并将其添加到表中。

我希望能够将函数的“包”安装到表中,这让我认为我需要能够跟踪表的状态,因为它会在安装包时发生变化。我要找的是 Reader Monad 还是 State Monad?

4

1 回答 1

1

不需要单子。您的标记想法是正确的,但是该信息的编码方式可能与您预期的不同。

我将从命令的定义开始:

type Command = [String] -> IO ()

然后你可以制作“命令制作者”功能:

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

作为标签。如果你不喜欢函数的泛滥,你也可以做一个“命令 lambda”:

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 ++ "?"

当然mkCommand1etc. 可以很容易地写成arg, 为了两全其美。

至于包,Command充分封装了多个子命令之间的选择,但它们不组合。这里的一种选择是更改Command为:

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

这允许您Command通过采取不返回的第一个操作将多个 s 组合成一个Nothing。现在你的包也只是类型的值Command。(总的来说,对于 Haskell,我们对这些组合非常感兴趣——而不是包和列表,考虑如何将某个对象中的两个作为组合对象)

为了使您摆脱您肯定建立的愿望:(1)没有合理的方法来检测函数接受的参数数量*,并且(2)没有办法使类型依赖于数字,所以您将无法创建将参数数量mkCommand作为第一个参数的 a Int

希望这有帮助。

  • 在这种情况下,事实证明是有的,但我建议不要这样做,并认为这是一个坏习惯——当事情变得更抽象时,技术就会失效。但我是个纯粹主义者;更多的胶带Haskellers可能不同意我的观点。
于 2012-04-07T08:53:58.443 回答