Scala cast to generic type (for generic numerical function)

前端 未结 1 1597
不思量自难忘°
不思量自难忘° 2021-02-10 02:11

I\'m trying to implement a generic function that wraps a mathematical Java function. For simplicity, we can assume that the Java function (Java 7) takes one parameter and return

1条回答
  •  借酒劲吻你
    2021-02-10 02:49

    You can't cast Double to Integer anyway (because it's boxed). Numeric just allows you to have a set of mathematical operations (by import num._) on your T - nothing else (you don't need some mediate type for that). A2 works only because println expecting Any as a result of f(3), so T is automatically inferred to Any; println(f[Int](3)) will never work, f[Any](3) will always work.

    If you want to implement generic function which operates Doubles (you may need that only if you have operations specific to Double) - you should better return Double. If you can't - you will have to construct the type manually by analizing T:

    def f[A](x: A)(implicit num: Numeric[A]): A = {
       val result = new java.lang.Double(num.toDouble(x))
       (x match {
           case x: Double => result
           case x: Int => result.toInt
           case x: Float => result.toFloat
           case x: Long => result.toLong
       }).asInstanceOf[A]
    }
    

    The reason why you can't just do result.doubleValue.asInstanceOf[A] here is that A is already boxed. @specialized annotation doesn't work for asInstanceOf (type A is still boxed)

    UPDATE: actually @specialized works:

    def f[@specialized(Int, Double, Long, Float) A](x: A)(implicit num: Numeric[A]): A = {
       val result = new java.lang.Double(num.toDouble(x)) 
    
       result.doubleValue.asInstanceOf[A]
    }
    

    But it doesn't work in Scala REPL - so be careful!

    P.S. Manifests are deprecated: use classTag/typeTag instead

    0 讨论(0)
提交回复
热议问题