Make42 - 1 year ago 71
Scala Question

# How to write a currying Scala Function trait?

## Issue

### First approach

If would like to have

``````trait Distance extends ((SpacePoint, SpacePoint) => Double)

object EuclideanDistance extends Distance {
override def apply(sp1: SpacePoint, sp2: SpacePoint): Double = ???
}

trait Kernel extends (((Distance)(SpacePoint, SpacePoint)) => Double)

object GaussianKernel extends Kernel {
override def apply(distance: Distance)(sp1: SpacePoint, sp2: SpacePoint): Double = ???
}
``````

However the
`apply`
of
`object GaussianKernel extends Kernel`
is not an excepted
`override`
to the
`apply`
of
`trait Kernel`
.

### Second approach - EDIT: turns out this works afterall...

Alternatively I could write

``````trait Kernel extends ((Distance) => ( (SpacePoint, SpacePoint)  => Double))

object GaussianKernel extends Kernel {
override def apply(distance: Distance): (SpacePoint, SpacePoint) => Double =
(sp1: SpacePoint, sp2: SpacePoint) =>
math.exp(-math.pow(distance(sp1, sp2), 2) / (2))
}
``````

but am not sure this is currying...

EDIT: Turns out that I can use this second approach in a currying fashion. I think it is exactly what the typical currying is, only without the syntactic sugar.

## Explanation of the idea

The idea is this: For my algorithm I need a Kernel. This kernel calculates a metric for two vectors in space - here
`SpacePoint`
s. For that the Kernel requires a way to calculate the distance between the two
`SpacePoint`
s. Both distance and kernel should be exchangeable (open-closed principle), thus I declare them as traits (in Java I had them declared as interfaces). Here I use the Euclidean Distance (not shown) and the Gaussian Kernel. Why the currying? Later when using those things, the
`distance`
is going to be more or less the same for all measurements, while the
`SpacePoint`
s will change all the time. Again, trying to stay true to the open-closed principle. Thus, in a first step I would like the
`GaussianKernel`
to be pre-configured (if you will) with a distance and return a
`Function`
that can be feed later in the program with the
`SpacePoint`
s (I am sure the code is wrong, just to give you an idea what I am aiming at):

``````val myFirstKernel  = GaussianKernel(EuclideanDistance)
val mySecondKernel = GaussianKernel(FancyDistance)
val myThirdKernel  = EpanechnikovKernel(EuclideanDistance)
// ...  lots lof code ...
val firstOtherClass  = new OtherClass(myFirstKernel)
val secondOtherClass = new OtherClass(mySecondKernel)
val thirdOtherClass  = new OtherClass(myThirdKernel)

// ...  meanwhile in "OtherClass" ...
class OtherClass(kernel: Kernel) {
val thisSpacePoint = ??? // ... fancy stuff going on ...
val thisSpacePoint = ??? // ... fancy stuff going on ...
val calculatedKernel = kernel(thisSpacePoint, thatSpacePoint)
}
``````

## Questions

1. How do I build my trait?

2. Since
`distance`
can be different for different
`GaussianKernel`
s - should
`GaussianKernel`
be a class instead of an object?

3. Should I partially apply
`GaussianKernel`

4. Is my approach bad and
`GaussianKernel`
should be a class that stores the
`distance`
in a field?

### 1. How do I build my trait?

The second approach is the way to go. You just can't use the syntactic sugar of currying as usual, but this is the same as currying:

``````GaussianKernel(ContinuousEuclideanDistance)(2, sp1, sp2)
GaussianKernel(ContinuousManhattanDistance)(2, sp1, sp2)

val eKern = GaussianKernel(ContinuousEuclideanDistance)

eKern(2, sp1, sp2)
eKern(2, sp1, sp3)

val mKern = GaussianKernel(ContinuousManhattanDistance)

mKern(2, sp1, sp2)
mKern(2, sp1, sp3)
``````

### Why the first approach does not work

Because currying is only possible for methods (duh...). The issue starts with the notion that a Function is very much like a method, only that the actual method is the apply method, which is invoked by calling the Function's "constructor".

First of all: If an object has an apply method, it already has this ability - no need to extend a Function. Extending a Function only forces the object to have an apply method. When I say "object" here I mean both, a singleton Scala object (with the identifier `object`) and a instantiated class. If the object is a instantiated class `MyClass`, then the call `MyClass(...)` refers to the constructor (thus a `new` before that is required) and the apply is masked. However, after the instantiation, I can use the resulting object in the way mentioned: `val myClass = new MyClass(...)`, where myClass is an object (a class instance). Now I can write `myClass(...)`, calling the apply method. If the object is a singleton object, then I already have an object and can directly write `MyObject(...)` to call the apply method. Of course an object (in both senses) does not have a constructor and thus the apply is not masked and can be used. When this is done, it just looks the same way as a constructor, but it isn't (that's Scala syntax for you - just because it looks similar, doesn't mean it's the same thing).

Second of all: Currying is syntactic sugar:

``````def mymethod(a: Int)(b: Double): String = ???
``````

is syntactic sugar for

``````def mymethod(a: Int): ((Double) => String) = ???
``````

which is syntactic sugar for

``````def mymethod(a: Int): Function1[Double, String] = ???
``````

thus

``````def mymethod(a: Int): Function1[Double, String] = {
new Function1[Double, String] {
def apply(Double): String = ???
}
}
``````

(If we extend a FunctionN[T1, T2, ..., Tn+1] it works like this: The last type Tn+1 is the output type of the apply method, the first N types are the input types.)

Now, we want the apply method here is supposed to be currying:

``````object GaussianKernel extends Kernel {
override def apply(distance: Distance)(sp1: SpacePoint, sp2: SpacePoint): Double = ???
}
``````

which translates to

``````object GaussianKernel extends Kernel {
def apply(distance: Distance): Function2[SpacePoint, SpacePoint, Double] = {
new Function2[SpacePoint, SpacePoint, Double] {
def apply(SpacePoint, SpacePoint): Double
}
}
}
``````

Now, so what should `GaussianKernel` extend (or what is `GaussianKernel`)? It should extend

``````Function1[Distance, Function2[SpacePoint, SpacePoint, Double]]
``````

(which is the same as `Distance => ((SpacePoint, SpacePoint) => Double))`, the second approach).

Now the issue here is, that this cannot be written as currying, because it is a type description and not a method's signature. After discussing all this, this seems obvious, but before discussion all this, it might not have. The thing is, that the type description seemed to have a direct translation into the apply method's (the first, or only one, depending on how one takes the syntactic sugar apart) signature, but it doesn't. To be fair though, it is something that could have been implemented in the compiler: That the type description and the apply method's signature are recognized to be equal.

### 2. Since distance can be different for different GaussianKernels - should GaussianKernel be a class instead of an object?

Both are valid implementation. Using those later only differenciates only in the presence or absence of `new`.

If one does not like the `new` one can consider a companion object as a Factory pattern.

### 3. Should I partially apply GaussianKernel instead of currying?

In general this is preferred according to http://www.vasinov.com/blog/on-currying-and-partial-function-application/#toc-use-cases

An advantage of currying would be the nicer code without `_: ???` for the missing parameters.

### 4. Is my approach bad and GaussianKernel should be a class that stores the distance in a field?

see 2.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download