Is this a valid example of Currying in Java

Viewed 222

I am trying to understand currying in Java and have created the following simple example. Is this a valid example of currying or have I missed the point?

    // Before
    House constructHouse1(Foundation f, Building b) {
        return new House(f, b);
    }

    // After
    House constructHouse2(Foundation f, Building b) {
        return constructHouseWithBuilding(b).apply(f);
    }

    Function<Foundation, House> constructHouseWithBuilding(Building b) {
        return constructHouseWithFoundation(b);
    }

    Function<Foundation, House> constructHouseWithFoundation(Building b) {
        return foundation -> new House(foundation, b);
    }

    // Beans
    class Foundation { }
    class Building { }
    class House {
        Foundation f;
        Building b;
        House(Foundation f, Building b) {
            this.f = f;
            this.b = b;
        }
    }
2 Answers

Kind of.

By curried function we understand a function that instead of taking multiple parameters will take one argument and return another function until all parameters are returned. So instead of:

BiFunction<Foundation, Building, House> constructHouse = ...;

you would have

Function<Foundation, Function<Building, House>> curriedConstructHouse = ...;

We are talking about concepts here, not a particular implementation so we could consider these to be manually curried.

House constructHouse(Foundation f, Building b) {
    return new House(f, b);
}

Function<Foundation, House> constructHouseWithBuilding(Building b) {
    return f -> constructHouse(f, b);
}

Because type matters Foundation -> Building -> House is not the same as Building -> Foundation -> House. If we are talking about currying they are curried variants of two functions with different signatures: (Foundation, Building) -> House and (Building, Foundation) -> House.

If you wanted to apply several arguments to a function which have more arguments that you want to apply (no matter where they are) we usually talk about partial application. Seeing how currying is usually understood you could consider it a special case of a partial application, where you always partially apply the first argument from the list of remaining arguments, and all of the remaining arguments will we partially applied one at a time.

For that reason I would consider this a partial application:

House constructHouse(Foundation f, Building b) {
    return new House(f, b);
}

Function<Building, House> constructHouseWithFoundation(Foundation f) {
    return b -> constructHouse(f, b);
}

Maybe some more examples would clarify the differences (let's assume vavs or something that has function with more than 2 arguments, but this code is pseudocode):

A a; B c; C c; // arguments to pass
               // a1, b2, c1 will be used as arguments in lambdas to avoid confusion

// uncurried
// (A, B, C) -> D
Function3<A, B, C , D> f;
f.apply(a, b, c); // returns D

// curried
// A -> B -> C -> D
Function1<A, Function1<B, Function1<C, D>>> curried = f.curried(); // curried() is available in Vavr's functions
curried.apply(a).apply(b).apply(c); // returns D

// partially applied B
// (A, C) -> D
Function2<A, C, D> partially1 = (a1, c1) -> f(a1, b, c1); // there is no syntactic sugar for this in Java that I am aware of

// partially applied A and C
// B -> D
Function1<B, D> partially2 = (b1) -> f(a, b1, c); 

// neither currying nor partial application
Function3<C, A, B, D> reordered = (c1, a1, b1) -> f(a1, b1, c1);

So I could consider your constructHouseWithFoundation to be curried function, and constructHouse2 to be uncurried version of constructHouseWithFoundation.

Currying refers to transforming a function of multiple arguments into a function of a single argument that returns another function, which takes the remaining arguments. For two argument functions this can be implemented in Java like so:

static <T, U, R> Function<T, Function<U, R>> curry(BiFunction<T, U, R> f) {
    return t -> u -> f.apply(t, u);
}

With this

Objects.equals("one", "two");

is equivalent to

curry(Object::equals)
    .apply("one")
    .apply("two");

Another way to look at currying, which is more idiomatic to Java is the following:

A currency exchange function is a function taking a rate and an amount argument and returns the exchange:

static double change(double rate, double amount) { 
    return rate * amount; 
}

To convert multiple amounts with the same exchange rate you could encapsulate the rate in an Exchange class:

class Exchange {
    final double rate;
    Exchange(double rate) {this.rate = rate;}

    double change(double amount) { 
        return rate * amount; 
    }
}

This is pretty much currying: the constructor of Exchange takes a single argument and returns an instance of Exchange for a fixed rate. This in turn is essentially a function of the single argument amount. To make this more apparent, note how the two functions exchange1 and exchange2 are equivalent to each other:

Function<Double, Double> exchange1 = new Exchange(1.3)::change;
Function<Double, Double> exchange2 = curry(Outer::change).apply(1.3);
Related