2017-07-21 5 views
0

タイトルを持つYouTube動画を視聴した後、Scala Type Members vs Type Parameters。私は以下を書いた。純粋なタイプのパラメータとメンバーとの混合タイプのパラメータ

  1. 純粋型パラメータバージョンは細かい

    trait Joiner[Elem,R] { 
        def join(xs: Seq[Elem]): R 
    } 
    
    
    
    object Program { 
    
        def doJoin[T,R] (xs: T *) (implicit j: Joiner[T,R]): R = j.join (xs) 
    
        def main(args: Array[String]): Unit = { 
    
    
        implicit val charToStringJoiner = new Joiner[Char,String] { 
         override def join(xs: Seq[Char]): String = xs.mkString("+") 
        } 
        implicit val charToInt = new Joiner[Char,Int] { 
         override def join(xs: Seq[Char]): Int = xs.mkString.toInt 
        } 
    
    
        val s:String = doJoin[Char,String]('1','2') 
        println(s) 
        val n :Int = doJoin[Char,Int]('1','2') 
        println(n) 
    
        } 
    
    } 
    
  2. 混合型のメンバ&パラメータバージョン働く -

    trait Joiner[Elem] { 
         type R 
         def join(xs: Seq[Elem]): R 
        } 
    
    
        object Program { 
    
        def doJoin[T] (xs: T *) (implicit j: Joiner[T]): j.R = j.join (xs) 
    
         def main(args: Array[String]): Unit = { 
    
         implicit val charToStringJoiner = new Joiner[Char] { 
          override type R = String 
          override def join(xs: Seq[Char]): String = xs.mkString("+") 
         } 
    
         implicit val charToInt = new Joiner[Char] { 
          override type R = Int 
          override def join(xs: Seq[Char]): Int = xs.mkString.toInt 
         } 
    
         val s:String = doJoin('1','2') //doesn't work 
         println(s) 
         val n :Int = doJoin('1','2') //doesn't work 
         println(n) 
    
         } 
    
        } 
    

バージョン1をただし、バージョン2で結構ですコンパイルされません。どのようにスコープ内に暗黙のうちにこれを修正することができますか?具体的にどのように私はコンパイラが正しい暗黙的に解決するのに役立つ戻り値の型を指定することができます

+0

私はそれができるとは思わない。ほとんどの状況下では、コンパイラは最初のパラメータリストでしか曖昧さを解消できません。 – jwvh

答えて

0

問題は、スコープ内の同じ種類の結合子[Char]で2つの暗黙のvalを持つことです。 は、異なる機能にそれらを分割し、それが動作するはずです:

object Program { 

    def doJoin[T] (xs: T *) (implicit j: Joiner[T]): j.R = j.join (xs) 

    def main(args: Array[String]): Unit = { 

    def do1: Unit ={ 
     implicit val charToStringJoiner = new Joiner[Char] { 
     override type R = String 
     override def join(xs: Seq[Char]): String = xs.mkString("+") 
     } 
     val s:String = doJoin('1','2') //doesn't work 
     println(s) 
    } 

    def do2: Unit ={ 
     implicit val charToInt = new Joiner[Char] { 
     override type R = Int 
     override def join(xs: Seq[Char]): Int = xs.mkString.toInt 
     } 
     val n :Int = doJoin('1','2') //doesn't work 
     println(n) 
    } 

    do1 
    do2 


    } 

} 
+0

はい。スコープ内に暗黙のうちに1つ、それはいいです。暗黙の候補者が2人いると、それは分解されますが、両方の型を指定できるので、純粋なパラメータ型は関係なく動作します。だから問題は、コンパイラが暗黙的に解決するのを手助けするために、戻り値の型を明示的に指定できないことに注意して、混合バージョンを動作させる方法です。 – lawal

0

をどのようにこのことについて。戻り値の型を指定することができ、入力型は引数から取り出されます。

import scala.language.reflectiveCalls 

trait Joiner[T, R] { 
    def join(xs: Seq[T]): R 
} 

def doJoin[R] = new { 
    def apply[T](xs: T*)(implicit j: Joiner[T, R]): R = j.join(xs) 
} 

implicit val charToStringJoiner = new Joiner[Char, String] { 
    override def join(xs: Seq[Char]): String = xs.mkString("+") 
} 

implicit val charToInt = new Joiner[Char, Int] { 
    override def join(xs: Seq[Char]): Int = xs.mkString.toInt 
} 

implicit val addJoiner = new Joiner[Int, Int] { 
    override def join(xs: Seq[Int]): Int = xs.sum 
} 

println(doJoin[String]('1', '2')) 
println(doJoin[Int]('1', '2')) 
println(doJoin[Int](1, 2)) 
関連する問題