Structural typing in Scala: use an abstract type in the refinement

Let's say I have the following code:

class Bar { def bar(b:Bar):Boolean = true } def func(b:Bar) = b.bar(b) 

The above works fine. The Bar class is defined in a third-party library, and there are several similar classes, each of which has a Bar method, for example

 class Foo { def bar(f:Foo):Boolean = false } 

Instead of writing func for each such class, I want to define func using the generic type B , since it has the Bar method of the correct signature.

I tried the following, but this gives me an error:

 def func[B <: {def bar(a:B):Boolean}](b:B) = b.bar(b) // gives error 

The error I get is:

 <console>:16: error: Parameter type in structural refinement may not refer to an abstract type defined outside that refinement def func[B <: {def bar(a:B):Boolean}](b:B) = b.bar(b) ^ 

However, if I do the following, the method definition works, but the call causes an error:

 def func[B <: {def bar(a:Any):Boolean}](b:B) = b.bar(b) func(new Bar) <console>:10: error: type mismatch; found : Bar required: B func(new Bar) ^ 

Is there a way to do what I want without changing the Bar code?

+7
scala structural-typing
source share
1 answer

It is enough to know the problem with the abstract type defined outside the structural type for the method parameter. Secondly, your approach does not work, because the method signatures are not equal (it looks like method overloading).

I suggest using a workaround. The functional approach of the method definition, since Function1 [-T1, + R] is known as:

 class Bar { def bar : Bar => Boolean = _ => true } class Foo { def bar : Foo => Boolean = _ => false } def func[T <: { def bar : T => Boolean } ](b: T): Boolean = b.bar(b) func(new Bar) func(new Foo) 

Symbols <and> Method type here

+2
source share

All Articles