Kevin Meredith
Kevin Meredith

Reputation: 41919

Overriding Method (Int => Int => Int) of Trait

Given the following trait:

scala> trait Foo { 
     |   def f: Int => Int => Int
     | }
defined trait Foo

I created a class that tried to instantiate Foo#f:

scala> class FooImpl extends Foo {
     |  override def f(x: Int, y: Int) = 100
     | }
<console>:11: error: class FooImpl needs to be abstract, since method f in trait Foo of type => Int => (Int => Int) is not defined
       class FooImpl extends Foo {
             ^

I was able to resolve it with:

scala> class FooImpl extends Foo {
     |   override def f = x => y => 100
     | }
defined class FooImpl

Then I can make an instance:

scala> new FooImpl().f(10)(20)
res3: Int = 100

But, how would I create an implementation of Foo that implements Foo#f with def f(x: Int, y: Int) = 100, i.e. without currying?

Lastly, I tried:

scala> trait Bar { def f: (Int, Int) => Int }
defined trait Bar

But that failed too:

scala> class BarImpl extends Bar { 
     |  override def f(x: Int, y:Int) =100
     | }
<console>:11: error: class BarImpl needs to be abstract, since method f in trait Bar of type => (Int, Int) => Int is not defined
       class BarImpl extends Bar {
             ^

Upvotes: 1

Views: 84

Answers (3)

Puneeth Reddy V
Puneeth Reddy V

Reputation: 1568

This is how can create FooImpl that implements Foo trait. We can also access Foo#f without currying.

trait Foo{
def f1:Int=> Int=> Int
def f2: (Int, Int) => Int
}

class FooImpl extends Foo{

    //actual implementors of f1 and f2 in Foo trait
    def g0=g1
    def g1=g2
    def g2=20
    def add(a:Int, b:Int)=a+b

    override  def f1=g0=>g1=>g2
    override def f2=add 
}

Now we can instantiate FooImpl class without currying.

var x = new FooImpl
println(x.f1.apply(1).apply(1))  //results 20
println(x.f2(10,10))             //results 20

Upvotes: 0

Michael Zajac
Michael Zajac

Reputation: 55569

Those types are incompatible.

def f: Int => Int => Int

.. Is a parameterless method that returns a function with one argument Int, that returns a function with one argument Int, that returns Int.

def f: (Int, Int) => Int

.. Is a parameterless method that returns a function with two arguments of type Int, that returns Int.

def f(x: Int, y: Int): Int

.. Is a two-parameter method with two Int arguments that returns an Int.

All of these are fundamentally different. You cannot override any of them with any other. If you want f(x: Int, y: Int): Int, then that is the signature that should be in Foo in the first place. Otherwise, you'll have to curry, eta-expand, or something else to make the signatures match.

Upvotes: 7

bjfletcher
bjfletcher

Reputation: 11518

If you wanted the trait to define the non-curried version, then it would need to be like this:

trait Foo {
  def f(x: Int, y: Int): Int
}

The (x: Int, y: Int) here says that f takes in two parameters of Int and the : Int says that the return value needs to be Int.

Upvotes: 0

Related Questions