Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Structural typing in Scala: use abstract type in refinement

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 class Bar is defined in a 3rd party library and there are several similar classes, each with 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 generic type B as long at it has a bar method of the correct signature.

I tried the following but it 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 invocation gives 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 any way to do what I want without changing the code of Bar?

like image 246
Jus12 Avatar asked Apr 09 '14 09:04

Jus12


1 Answers

It is enought know problem with abstract type defined outside structural type for method parameter. Second your approach doesn't work because method signatures is not equal (looks like method overloading).

I propose use workaround. Functional approach of method definition, because Function1[-T1, +R] is known type:

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) 

Cons & Pros functional type VS method type definition here

like image 116
Yuriy Avatar answered Oct 02 '22 11:10

Yuriy