2

The following code does not compile, as both multiplication operators have same type after erasure: (f: Object)Object

I know about type erasure, but all cases I have seen had erased the generic type, like List[Int] or List[String], as answered in Scala double definition (2 methods have the same type erasure).

How can I make the Scala treat different type XxxT` types different?

trait AbstractTypes {
  type ScalarT
  type VectorT
  abstract class Operators(u: VectorT) {
    def *(f: ScalarT): VectorT
    def *(v: VectorT): VectorT
  }
}
Community
  • 1
  • 1
Bébul
  • 525
  • 1
  • 4
  • 7

2 Answers2

6

This is what DummyImplicit is for:

trait AbstractTypes {
  type ScalarT
  type VectorT
  abstract class Operators(u: VectorT) {
    def *(f: ScalarT): VectorT
    def *(v: VectorT)(implicit dummy1: DummyImplicit): VectorT
  }
}

You can have any number of DummyImplicits if you need more overloads whose erasure are the same.

sjrd
  • 20,350
  • 2
  • 57
  • 81
0

Using one of the tricks from answer to the linked question (declaring parameter of the seconds method as call-by-name):

trait AbstractTypes {
  type ScalarT
  type VectorT
  abstract class Operators(u: VectorT) {
    def *(f: ScalarT): VectorT
    def *(v: => VectorT): VectorT
  }
}

object ConcreteTypes extends AbstractTypes {
  type ScalarT = Double
  type VectorT = Seq[Double]
  class ConcreteOperators(u: Seq[Double]) extends Operators(u) {
    def *(f: Double): Seq[Double] = u.map(_ * f)
    def *(v: => Seq[Double]): Seq[Double] = 
      (u zip v).map { case (a, b) => a * b }
  }
}

new ConcreteTypes.ConcreteOperators(Seq(2.0, 3.0, 5.0)) * 7.0 
Seq[Double] = List(14.0, 21.0, 35.0)

new ConcreteTypes.ConcreteOperators(Seq(2.0, 3.0, 5.0)) * Seq(1.0, 2.0, 3.0) 
Seq[Double] = List(2.0, 6.0, 15.0)
Community
  • 1
  • 1
adamwy
  • 1,221
  • 1
  • 6
  • 12
  • Interesting trick, but it changes the semantics a little. When you use the function instead of the value, for instance, every usage calls the function again. – Bébul Jan 13 '17 at 09:41