纯类型参数和带有成员的混合类型参数

时间:2017-07-21 07:19:11

标签: scala generics types implicits

观看标题为Scala Type Members vs Type Parameters的youtube视频后。我写了以下内容。

  1. Purely Type参数版本可以正常使用

     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)
    
          }
    
        }
    
  3. 版本1很好,但版本2不能编译。如何在隐含范围内修复此问题?具体来说,我如何指定有助于编译器解析正确的隐式

    的返回类型

2 个答案:

答案 0 :(得分:0)

问题是你有两个隐式val,范围内的Joiner [Char]类型相同。 将它们拆分为不同的功能,它应该可以工作:

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


  }

}

答案 1 :(得分: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))