Assume the following trait:
trait A {
type B
def +(a:A):A
}
I use an abstract type because I don't want to drag around the B in the type signature everytime I need an A. I开发者_如何转开发s it still possible to add any implicit evidence (using =:=,<:<, etc.) to the + method so that the compiler can still enforce acceptance of a:A's with identical B's?
My first instinct is to say no, but scala has pleasantly surprised me before. Any help would be appreciated.
No need for implicit evidence ... you can use an explicit refinement,
trait A {
self =>
type Self = A { type B = self.B }
type B
def +(a : Self) : Self
}
(note the use of a self type annotation to provide an alias for the outer 'this' allowing the defined and defining B's to be distinguished in the definition of type Self).
REPL transcript,
scala> trait A { self => type Self = A { type B = self.B } ; type B ; def +(a : Self) : Self }
defined trait A
scala> val ai = new A { type B = Int ; def +(a : Self) : Self = this }
ai: java.lang.Object with A{type B = Int} = $anon$1@67f797
scala> val ad = new A { type B = Double ; def +(a : Self) : Self = this }
ad: java.lang.Object with A{type B = Double} = $anon$1@7cb66a
scala> ai + ai
res0: ai.Self = $anon$1@67f797
scala> ad + ad
res1: ad.Self = $anon$1@7cb66a
scala> ai + ad
<console>:9: error: type mismatch;
found : ab.type (with underlying type java.lang.Object with A{type B = Double})
required: ai.Self
ai + ab
精彩评论