没有必要的单子。您的标记理念是正确的,但这些信息的编码方式可能与预期不同。
我将开始与命令的定义:
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
。
希望这有助于。
- 在这种情况下,事实证明存在这种情况,但我建议不要这样做,并认为这是一种坏习惯 - 当事情变得更抽象时,技术就会崩溃。但我是纯粹主义者;哈斯克勒斯可能会不同意我的观点。
我只是希望我有Haskell技能,能够成为一个纯粹哈哈。你认为你可以详细说明该功能如何作为标签吗?或者该类型用作标签。我仍然困惑。顺便说一句,这不是一个家庭作业问题或任何事情。这只是一个我帮助我学习的小型Haskell项目。 – 2012-04-07 22:00:21