我需要哪个Monad?

时间:2012-04-07 08:20:36

标签: haskell monads

这是这个问题的延伸:

Dispatching to correct function with command line arguments in Haskell

因此,事实证明,我还没有一个很好的解决方案来从命令行向其他功能发送“命令”。所以,我想在上面的问题中扩展方法。将函数手动添加到表并将适当的转换函数应用于每个函数以使其获取正确大小的列表而不是其正常参数似乎很麻烦。相反,我想构建一个表格,我将在其中添加函数,并使用从命令行获取的参数数量“标记”它们。然后,“添加”过程应该使用正确的“takesXarguments”过程进行合成并将其添加到表中。

我希望能够在表中安装“函数包”,这让我觉得我需要能够跟踪表的状态,因为它会在安装包时发生变化。读者Monad或State Monad是我正在寻找的吗?

1 个答案:

答案 0 :(得分:1)

不需要monad。您的标记理念是在正确的轨道上,但该信息的编码方式可能与您预期的不同。

我将从命令的定义开始:

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

当然,mkCommand1等可以用arg轻松编写,以实现两全其美。

对于包,Command充分封装了多个子命令之间的选择,但它们不构成。此处的一个选项是将Command更改为:

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

通过执行不返回Command的第一个操作,您可以将多个Nothing组合成一个Command。现在,您的包也只是mkCommand类型的值。 (一般来说,对于Haskell,我们对这些组合非常感兴趣 - 而不是包和列表,请考虑如何使用两个对象来制作复合对象)

为了避免你有所建立的愿望:(1)没有合理的方法来检测一个函数占用的参数数量*,以及(2)没有办法让一个类型取决于一个数字,因此您将无法创建Int作为参数数量的第一个参数{{1}}。

希望这会有所帮助。

  • 在这种情况下,事实证明存在,但我建议反对它并认为这是一个坏习惯 - 当事情变得更抽象时,技术会崩溃。但我是纯粹主义者;更多管道式的Haskellers可能不同意我的观点。