私はこのようなクラスのペアを持っています。いくつGenerator
かのクラスレベルの値に基づいて値を生成するaと、GeneratorFactory
を構築するaがありGenerator
ます。
case class Generator[T, S](a: T, b: T, c: T) {
def generate(implicit bf: CanBuildFrom[S, T, S]): S =
bf() += (a, b, c) result
}
case class GeneratorFactory[T]() {
def build[S <% Seq[T]](seq: S) = Generator[T, S](seq(0), seq(1), seq(2))
}
GeneratorFactory.build
型の引数を受け入れ、型の値S
をGenerator.generate
生成することに気付くでしょうが、によって格納される型の値はS
ありません。S
Generator
このようなクラスを使用できます。ファクトリはのシーケンスで動作し、が与えられているためChar
にをgenerate
生成します。String
build
String
val gb = GeneratorFactory[Char]()
val g = gb.build("this string")
val o = g.generate
これは問題なく、String
を使用しているため、型を暗黙的に処理しGeneratorFactory
ます。
問題
Generator
ここで、工場を経由せずにを構築したいときに問題が発生します。私はこれを行うことができるようにしたいと思います:
val g2 = Generator('a', 'b', 'c')
g2.generate // error
g2
しかし、タイプとScalaがあるため、エラーが発生しますGenerator[Char,Nothing]
。「タイプNothingのコレクションに基づいて、タイプCharの要素を使用してタイプNothingのコレクションを構築することはできません。」
私が欲しいのは、の「デフォルト値」がの代わりのS
ようなものであることをScalaに伝える方法です。デフォルトパラメータの構文から借用すると、これは次のようなものと考えることができます。Seq[T]
Nothing
case class Generator[T, S=Seq[T]]
不十分なソリューション
もちろん、生成されたタイプがどうあるべきかをジェネレーターに明示的に指示すれば機能しますが、デフォルトのオプションの方が良いと思います(私の実際のシナリオはより複雑です)。
val g3 = Generator[Char, String]('a', 'b', 'c')
val o3 = g3.generate // works fine, o3 has type String
オーバーロードを1つのジェネリック型バージョンにすることを考えましたが、Scalaは2つの定義Generator.apply
を区別できないため、エラーが発生します。apply
object Generator {
def apply[T](a: T, b: T, c: T) = new Generator[T, Seq[T]](a, b, c)
}
val g2 = Generator('a', 'b', 'c') // error: ambiguous reference to overloaded definition
必要な出力
私が欲しいのはGenerator
、タイプを指定せずに単純にを構築し、S
それをデフォルトにして、次のSeq[T]
ことができるようにする方法です。
val g2 = Generator('a', 'b', 'c')
val o2 = g2.generate
// o2 is of type Seq[Char]
これがユーザーにとって最もクリーンなインターフェースになると思います。
これを実現する方法はありますか?