2017-07-21 3 views
0

Après avoir regardé une vidéo sur YouTube avec le titre Scala Type Membres vs Type Paramètres. J'ai écrit ce qui suit.Paramètres de type pur et paramètre de type mixte avec le membre

  1. version paramètre Purement type fonctionne bien

    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. Membre Mixte Type & version Paramètre -

    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) 
    
         } 
    
        } 
    

version 1 est bien la version cependant 2 ne compile pas. Comment cela peut-il être fixé en ayant à la fois une portée implicite? Spécifiquement, comment puis-je spécifier le type de retour qui aidera le compilateur à résoudre l'implicite correct

+0

Je ne pense pas que ce soit possible. Dans la plupart des cas, le compilateur ne peut être désambiguïsé que sur la première liste de paramètres. – jwvh

Répondre

0

Le problème est que vous avez deux Val implicite avec les mêmes types Joiner [Char] dans la portée. les Split à des fonctions différentes et il devrait fonctionner:

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

Oui. avec un implicite dans la portée, c'est bien. Avec deux candiates implicites, il se décompose alors que le type purement parametrique fonctionne indépendamment du fait que je peux spécifier les deux types. Donc, la question est de savoir comment faire fonctionner la version mixte en notant que je ne peux pas spécifier explicitement le type de retour pour aider le compilateur à résoudre l'implicite. – lawal

0

Comment à ce sujet. Vous pouvez spécifier votre type de retour et le type d'entrée est extrait de l'argument.

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))