異なるトラバースの複数のクロス積を構築しようとしています。望ましい戻り値の型は、入力traversablesの型と一致する型のタプルのトラバーサブルです。たとえば:Scala:複数のソースと異種の型を持つクロス(デカルト)プロダクト
List(1, 2, 3) cross Seq("a", "b") cross Set(0.5, 7.3)
これは、次の3つのソースからのすべての可能な組み合わせでTraversable[(Int, String, Double)]
を与える必要があります。 2つのソースのみを組み合わせた場合は、うまくanswered hereでした。
implicit class Crossable[X](xs: Traversable[X]) {
def cross[A](ys: Traversable[A]) = for { x <- xs; y <- ys } yield (x, y)
}
コメントが簡単に複数のソースの問題に言及したが、私はどちらか一方(型崩れやscalaz、私は「ドンに依存しない解決策を見つけるために探しています:与えられたアイデアがありますTuple22
までスケールアップするための定型文を持っている)。私は何をしたいのは、次のようなものです:
implicit class Crossable[X](xs: Traversable[X]) {
def cross[A](ys: Traversable[A]) = for { x <- xs; y <- ys } yield (x, y)
def cross[A,B](ys: Traversable[(A,B)]) = // ... extend all Tuple2's in ys with x in xs to Tuple3's
def cross[A,B,C](ys: Traversable[(A,B,C)]) = // ...
// ...
}
これは明らかに伴う型消去に動作しません(と、残念ながら、おそらくcross
は右結合になるので、上記の例では、括弧を使用する必要があります)。
私の質問です:問題を解決するためにScala 2.10のリフレクション機能を利用することはどういうことですか?一般に、A
とX
の両方をさまざまなタプルタイプ(およびそのタイプパラメータ、これは難しいと思われる)にマッチさせ、それらを大きなタプルにマージすると、連想法を満たす解決策が提供されるはずです。
うわー、それはかなりクールです!どうもありがとうございました!右結合バージョンを追加することも、このアプローチでは簡単です。私はtrait(それ以外の場合は常に一致する)に 'crosser2'を導入することで、"あいまいな暗黙の "コンパイラエラーを取り除いたことに気付きました。私は暗黙のためにある種のクラス階層依存優先ルールがなければならないと思いますか?私がまだ困惑しているもの:なぜcrosser2、crosser3、...が実際に範囲内にあるのですか?私は、「Crosser._」をインポートする必要があると予想していましたが、それはそうではないようです。 – bluenote10
他の誰かがこれを使いたい場合:私はちょっとしたコードジェネレーター(マクロをいつか学ばなければならない)を書いて、[Gist](https://gist.github.com/bluenote10/5465957#file-crossproduct-scalaすべての定型文を適度に高いレベルまで含んでいます(19番目の型パラメータから、私は奇妙なコンパイラエラーが発生しますが、18は私にとっては十分以上のものです)。 – bluenote10
あなたが 'Crosser._'を実行する必要がないのは、' Crosser'が暗黙的に 'Crossable.cross'に渡されているからです。暗黙の解決規則は' T型の暗黙の値'があれば、コンパイラは自動的に' T 'のコンパニオンオブジェクト(もしあれば)のメンバーを調べます。 SLS 7.2を参照してください –