cloudcalvin
5/28/2019 - 3:00 PM

avoiding-scala-trait-name-clashes.scala

Similarly named abstract types must conform when mixed together:

scala> trait Foo { type T }
defined trait Foo

scala> trait Bar { type T }
defined trait Bar

scala> trait FooBar { this: Foo with Bar => }
defined trait FooBar

scala> trait FooImpl extends Foo { type T = Int }
defined trait FooImpl

scala> trait BarImpl extends Bar { type T = Double }
defined trait BarImpl

scala> trait FooBarImpl extends FooBar with FooImpl with BarImpl
<console>:12: error: trait FooBarImpl inherits conflicting members:
  type T in trait FooImpl, which equals Int  and
  type T in trait BarImpl, which equals Double
(Note: this can be resolved by declaring an override in trait FooBarImpl.)
       trait FooBarImpl extends FooBar with FooImpl with BarImpl



trait AddComponent {
  type T
  def addition: Add

  trait Add {
    def constant: T
    def plus( t1: T, t2: T ): T
    def add( t: T ) = plus( t, constant )
  }
}

trait MulComponent {
  type T
  def multiplication: Mul

  trait Mul {
    def constant: T
    def times( t1: T, t2: T ): T
    def mul( t: T ) = times( t, constant )
  }
}

trait OperationsComponent { this: AddComponent with MulComponent =>
  def operations: Operations

  trait Operations {
    def neg( t: T ): T
  }
}

Here, it is ensured that T of Add and Mul are compatible, and that is all that the Operations trait really cares about.