Cake pattern and types

290 views Asked by At

How can def someA (in trait B) use trait A with the same C#MyType as in B ? (Then A#MyType =:= B#MyType)

trait C {
  type MyType
}


trait A {
  self: C =>
  def doSomething(s: MyType) { println(s.toString)}
}

trait B {
  self: C =>  

  def someA: A
  def myType: MyType

  def action = someA.doSomething(myType)
}

// Mix part

case class Ahoy(value: String)

trait ConcreteC extends C {  
  type MyType = Ahoy
}


class PieceOfCake extends B with ConcreteC {
  val someA = new A with ConcreteC
  val myType = Ahoy("MyType")

}

It doesn't compile : type mismatch;

[error]  found   : B.this.MyType
[error]  required: _1.MyType where val _1: A
[error]   def action = someA.doSomething(myType))
2

There are 2 answers

1
Matthew Farwell On BEST ANSWER

You can declare doSomething and myType to use the path independent version of MyType, SomeType#MyType:

trait SomeType {
  type MyType
}


trait A {
  self: SomeType =>
  def doSomething(s: SomeType#MyType) { println(s.toString)}
}

trait B {
  self: SomeType =>  

  def someA: A
  def myType: SomeType#MyType

  def action = someA.doSomething(myType)
}
1
Tomer Gabel On

I'm pretty sure you can't do that, since path-independent types are just that - if A<>B then A#T is strictly different from B#T (i.e. A#T will never be =:= B#T).

That being said, it's safe to cast, so you can always do something like someA.doSomething(myType.asInstanceOf[someA#MyType]). Ugly but works.