2017-06-27 19 views
0

私は、各インスタンスを暗黙的に同じ型に変換できる一連のインスタンスを持っています。 このようなシーケンスを変換する最善の方法は何ですか?正確な型はコンパイラに利用可能であるときにのみ、暗黙を使用することができますシーケンス内の暗黙的な変換

class A 
    class B 

    trait Resolver { 
    def resolve: String 
    } 

    implicit class AResolver(a: A) extends Resolver { 
    def resolve: String = "a" 
    } 
    implicit class BResolver(b: B) extends Resolver { 
    def resolve: String = "b" 
    } 

    def resolveThem(a: Option[A], b: Option[B]): Iterable[String] = { 
    val resolvers: Seq[Resolver] = a ++ b // type error 
    val resolvers: Seq[Resolver] = List(a, b).collect{case Some(x: Resolver) => x} // empty 
    val resolvers: Seq[Resolver] = List(a, b).collect{case Some(x: A) => x} // unexpectedly for me but it is also type error when there is an x:A 
    val resolvers: Seq[Resolver] = List(a, b).collect{case Some(x: A) => x:Resolver} // works but returns only A as resolver 
    val resolvers: Seq[Resolver] = List(a, b).collect{case Some(x /*something that can be implicitly converted to Resolver*/) => x:Resolver} // Is it possible? 
    val resolvers: Seq[Resolver] = List(a.get, b.get) // this bad approach works 
    resolvers.map(_.resolve) // this is what I want as result 
    a.map(_.resolve) ++ b.map(_.resolve) // there is another way but if I have more arguments it becomes too long 
    } 
+1

私のために間違ったクラスの使用が間違っているようです – cchantep

答えて

2
  1. 。あなたのオブジェクトをシンプルなListに入れるとすぐに、個々のタイプが消えます。 (HListでも構いません)
  2. 2つの引数については、あなたの作業方法を使用してください。
  3. さらに多くの引数を使用する場合は、1つの引数を持つビルダーを使用することができます。

    trait Builder { 
        def add[A: Resolver](a: A): Builder = { 
        use(a.resolve) 
        this 
        } 
    } 
    
  4. のみいくつかのクラスがある場合、あなたはランタイム一致使用することができます

    def getResolver(any: Any): Resolver = any match { 
        case a: A => a: Resolver 
        case b: B => b: Resolver 
        case _ => throw new IllegalArgumentException(s"$any is not supported" 
    } 
    

    をしかし、このアプローチは非常に非常に悪いです。それは拡張可能ではありません。

  5. 暗黙的な変換の代わりに型クラスを使用することもできます。

    trait Resolvable[T] { 
        def resolve(a: T): String 
        } 
        implicit class AResolvable extends Resolvable[A] { 
        def resolve(a: A): String = "a" 
        } 
    

    これは好ましい方法です。

0

その関数が唯一の可能な入力引数Aと暗黙的な変換のサブセットに定義される意味PartialFunction[A, B]を受け付けるcollect方法が適用されないであろう。

変換は、明示的に行うか事前に行う必要があります。あなたのケースでこれを行う方法の1つは、変数やシーケンスを取るメソッドです:

def resolveThem (resolvers: Option[Resolver]*): Iterable[String] = { 
    resolvers.flatten.map(_.resolve) 
} 

resolveThem(Option(new A), Option(new B)) 
関連する問題