2017-03-23 11 views
2

が、私は基本的に推測共通スーパータイプ

def merge[A, B, C](eithers: Either[A,B]*)(implicit ev1: A <:< C, ev2: B <:< C): Seq[C] = 
    eithers.flatMap(_.fold(Option[C](_), Option[C](_))) 

を行うにしようとしています何ですが、私は、CはAの共通スーパータイプであるSeq[C]Either[A,B]のリストを「フラット化」したいですとB(明らかにAny以外)。例えば

trait Foo 
    class Bar extends Foo 
    class Baz extends Foo 

    merge(Left[Bar, Baz](new Bar), Right[Bar, Baz](new Baz)) 

これは動作しません:( それはCannot prove that Baz <:< C

これを言うが、しかし、作業を行います。

merge[Bar, Baz, Foo](Left[Bar, Baz](new Bar), Right[Bar, Baz](new Baz)) 
    res7: Seq[Foo] = ArrayBuffer([email protected], [email protected]) 

ので、質問ができる人の事です一般的なスーパータイプに推論させるための何らかの仕掛けがありますので、このように綴る必要はありません。 または、少なくとも、aw 1つの型パラメータでのみこれを行うことができます(入力データの型を記述するのと同じように、結果の型を指定するのは気にしません)。

val merged: Seq[Foo] = merge(Left[Bar, Baz](new Bar), Right[Bar, Baz](new Baz)) 

これは動作しますが、私は宣言した変数を嫌うので、非常に、私のためにそれをカットしていない、一度だけ使用されています。私は後者を行うには知っている

一つの方法は、それを変数に割り当てるです。理想的には、私はこのような何かを探しています:

merge(input) 
    .filter(doILikeIt) 
    .map(doSomethingInteresting) 
// etc. 

アイデアはありますか?

+1

、B]は分散のために[C、C] 'のどちらかに広がる? –

答えて

4

簡単な解決策は、分散を使用して、あります:タイプの境界の代わりに、暗黙のパラメータを使用して

def merge[C](eithers: Either[C, C]*): Seq[C] = eithers.map(_.fold(x => x, x => x)) 
+0

どうして私はそれを考えなかったのですか? :D – Dima

2

は私の作品:

あなたはその `いずれかの[A事実を使用していないのはなぜ
def merge[A <: C, B <: C, C](eithers: Either[A,B]*): Seq[C] = 
    eithers.flatMap(_.fold(Option[C](_), Option[C](_)))