Search code examples
scalagenericstype-conversionimplicit

Scala Method on Generic Data Type


I am trying to create a generic class that only accepts java.math.BigDecimal or Long. Here is the code:

class myClass[T]()
{ 
    def display( x : T) = {
      println(x.doubleValue())
    }
}


val input = new java.math.BigDecimal(100)
// val input = 100L

val x = new myClass[java.math.BigDecimal]()
x.display(input)

Clearly I will have this error: ScalaFiddle.scala:22: error: value doubleValue is not a member of type parameter T.

I tried playing with implicit conversion, view bound, and context bound for hours. No result so far. Is there any way I can force Scala to believe me that T has method .doubleValue()? (java.big.Decimal and Long both has .doubleValue() method, but they don't share same super-class)


Solution

  • Try structural type bound

    class myClass[T <: {def doubleValue(): Double}]
    

    or type class

    trait HasDoubleValue[T] {
      def doubleValue(t: T): Double
    }
    object HasDoubleValue {
      implicit val long: HasDoubleValue[Long] = t => t.doubleValue
      implicit val bigDecimal: HasDoubleValue[BigDecimal] = t => t.doubleValue
    }
    
    implicit class DoubleValueOps[T: HasDoubleValue](x: T) {
      def doubleValue(): Double = implicitly[HasDoubleValue[T]].doubleValue(x)
    }
    
    class myClass[T: HasDoubleValue]