Reputation: 41919
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
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
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
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