Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use implicit evidence to force static type compatibility between abstract types?

Tags:

scala

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. Is 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.

like image 532
user44242 Avatar asked May 06 '11 10:05

user44242


People also ask

Can we use abstract and static together?

Declaring abstract method static If you declare a method in a class abstract to use it, you must override this method in the subclass. But, overriding is not possible with static methods. Therefore, an abstract method cannot be static.

Why static method is not allowed in interface?

Because static methods cannot be overridden in subclasses, and hence they cannot be abstract. And all methods in an interface are, de facto, abstract. You could always force each type to implement any static interface methods.

What can an abstract class have that an interface Cannot?

Type of variables: Abstract class can have final, non-final, static and non-static variables. The interface has only static and final variables. Implementation: Abstract class can provide the implementation of the interface. Interface can't provide the implementation of an abstract class.

Can we override static method in interface?

Similar to Default Method in Interface, the static method in an interface can be defined in the interface, but cannot be overridden in Implementation Classes.


1 Answers

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
like image 131
Miles Sabin Avatar answered Sep 22 '22 01:09

Miles Sabin