Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upper and Lower bound on scala type

Consider the following hierarchy:

class C1
class C2 extends C1
class C3 extends C2
class C4 extends C3

I want to write a function that just accepts types C2 and C3. For that I thought of the following:

 def f [C >: C3 <: C2](c :C) = 0

I'd expect the following behaviour

f(new C1)  //doesn't compile, ok
f(new C2)  //compiles, ok
f(new C3)  //compiles, ok
f(new C4)  // !!! Compiles, and it shouldn't 

The problem is when calling it with C4, which I don't want to allow, but the compiler accepts. I understand that C4 <: C2 is correct and that C4 can be seen as a C3. But when specifying the bound [C >: C3 <: C2], I would expect the compiler to find a C that respects both bounds at the same time, not one by one.

Question is : Is there any way to achieve what I want, and if not, is the compiler trying to avoid some inconsistency with this?

Edit: from the answers I realized that my presumption is wrong. C4 always fulfills C >: C3, so both bounds are indeed respected. The way to go for my use case is C3 <:< C.

like image 320
Chirlo Avatar asked Dec 04 '22 02:12

Chirlo


1 Answers

Statically, yes. It's pretty simple to impose this constraint:

def f[C <: C2](c: C)(implicit ev: C3 <:< C) = 0

f(new C4) wouldn't compile now.

The problem is, it's probably not possible to prohibit the following behaviour at compile time:

val c: C3 = new C4
f(c)

Here variable c has static type C3, which passes any kind of typechecking by compiler, but it is actually a C4 at runtime.

At runtime you can of course check the type using reflection or polymorphism and throw errors or return Failure(...) or None

like image 68
Kolmar Avatar answered Dec 20 '22 08:12

Kolmar