モナドは必要ありません。タグ付けのアイデアは正しい方向に進んでいますが、その情報はおそらく予想とは異なる方法でエンコードされています。
コマンドの定義から始めます。
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
、etc. は , という言葉で簡単に書くことができarg
、両方の長所を活かすことができます。
パッケージに関しては、Command
複数のサブコマンド間の選択肢を十分にカプセル化しますが、それらは構成しません。ここでの 1 つのオプションは、次のように変更Command
することです。
type Command = [String] -> Maybe (IO ())
これにより、返されCommand
ない最初のアクションを実行することで、複数の を単一のに構成できますNothing
。これで、パッケージも型の値にすぎませんCommand
。(一般に、Haskell では、これらの構成に非常に関心があります。パッケージやリストではなく、2 つのオブジェクトを使用して複合オブジェクトを作成する方法を考えてください)
(1) 関数が取る引数の数を検出する合理的な方法がなく*、(2) 型を数値に依存させる方法がないため、mkCommand
最初の引数として引数の数の an を取るa を作成することはできませんInt
。
これが役に立ったことを願っています。
- この場合、あることがわかりましたが、私はそれをやめることをお勧めします。それは悪い習慣だと思います。物事がより抽象的になると、テクニックは機能しなくなります。しかし、私は純粋主義者です。ダクトテープのような Haskellers が私に反対するかもしれません。