foo
関数と言ってbar
noo
、私のプログラムの基本です。さらに、これらの関数はさまざまなシナリオ( foo1, bar1
、 foo2, bar2
など) でさまざまな方法で実装できますが、入力foo1
とfoo2
出力の型は同じです。いくつかの入力または構成によると、プログラムfoo1, bar1
はあるシナリオでは を使用し、別のシナリオでは を使用しfoo2, bar2
ます。
接尾辞 (1,2,3..) を に追加して、上記のように定義することもできますfoo, bar, noo
。ただし、サフィックスが長くなる可能性があるため、これはきれいではありません。foo1
with bar1
(vs. )の特別なバインドも許可しませんbar2
。
別の方法は、各シナリオを個別の として扱うことModule
です。これfoo, bar, noo
で、各ケースが適切にまとめられ、醜い接尾辞が回避されました。ただし、これにより、1 つのファイルがModule
. このアプローチのもう 1 つの欠点は、Modules
いくつかの類似点 (たとえば 3 つの機能) を共有しているにもかかわらず、これらが完全に分離されていることです。
さまざまなシナリオのさまざまなs が同じ入力と出力を持っているため、typeclass
解決策は高く評価されますが、私の頭には浮かびませんでした。foo
これらのアプローチの前述の欠点を回避するために、問題に対するHaskellのベストプラクティスがあるのではないかと思っています。
foo1 :: Double -> Double
bar1 :: Int -> Int
noo1 :: [Int] -> [Int]
foo2 :: Double -> Double
bar2 :: Int -> Int
noo2 :: [Int] -> [Int]
...
foo9 :: Double -> Double
bar9 :: Int -> Int
noo9 :: [Int] -> [Int]
編集:私がそれにどのようにアプローチするかを説明することは、議論に関連していると思いますJava Interface
(いくつかの素晴らしいが概念レベルの議論は、Java interface
この投稿とここにあります)。多くの場合、複雑になる可能性がありますが、ここオーバーロードは実際には簡潔です。Haskell typeclass
Java interface and class
interface Scenario {
double foo(double d);
int bar(int i);
Array<int> noo(Array<int> a);
}
class UseScenario {
void use(Scenario ss) {
ss.foo(...);
ss.bar(...);
ss.noo(...);
}
}
class S1 implements Scenario {
double foo(double d) {...};
int bar(int i) {...};
Array<int> noo(Array<int> a) {...};
}
class S2 implements Scenario {
double foo(double d) {...};
int bar(int i) {...};
Array<int> noo(Array<int> a) {...};
}