Is There Curry In This Dish?

Now that Java is dipping its toes into the waters of supporting functional programming styles, many of the tenets of functional programming come to mind, and it’s worth exploring what is possible in this brave new world. Two of those features are currying and partial application. So the question is, can Java be functional?

Currying and Partial Application - A Refresher

Currying (named after Haskell Curry) is the process of generating function invocations with multiple parameters via single-parameter functions that return follow-up functions. In a language that is purely functional, currying is the only way to handle multiple parameters, as a pure function only accepts one parameter, and always returns one value.

Most languages in practice have convenience support for multiple parameters (sometimes implemented via currying, like Haskell), or tuples, or both, so currying isn’t a requirement, but it is a very powerful tool.

As a concrete example, we can use a language most folks understand that has some functional bits: Javascript (you may not love it, but you can probably read it!)

Javascript does not require curried functions, and doesn’t have language-level knowledge of currying, but can be forced to do it since functions are first-class (it’s just not nearly as pretty or “always-on” as in Haskell, for example). In Javascript we can have this function:

1function add(a, b) {
2	return a + b;
3}
4
5add(1,2); // returns 3.

We can revisit this implementation as a curried version instead, and it could look like this:

1function add(a) {
2	return function(b) {
3		return a + b;
4	}
5}
6
7add(1)(2); // returns 3.

This allows us to define, and then carry around a halfway completed function (it allows you to “specialize” the function).

1var addOne = add(1);
2var val1 = addOne(2); // returns 3
3var val2 = addOne(3); // returns 4.

What the add(1) invocation has done is partially apply parameters to the underlying operation of adding a and b.

This leads us to the idea of partial application, which is the process of taking a function that involves multiple parameters, and generating a new function where some of those parameters are fixed or built-in.

Note that you can have partial application without currying. Where currying is the process of composing a multi-parameter function chain out of many small single parameter functions (increasing the number of parameters), partial application is the process of producing a simpler and more specific function out of a more general function (reducing the number of parameters).

Let’s flip our previous example on its head, and use partial application on our initial add function:

 1function add(a, b) {
 2	return a + b;
 3}
 4
 5// Partially apply this function in a new function.
 6var addOne = function(b) {
 7	return add(1, b);
 8};
 9
10var val1 = addOne(2); // returns 3.

Now, we’ve taken our add function, applied one of the parameters and passed through the other parameter, converting a two-parameter function into a one-parameter function that is more specialized for the task.

So What About Java 8?

There are many arguments that can be made in this space regarding Java’s ability for partial application and currying, and much of it depends on where you are coming from to make your arguments.

Academically speaking, Java unequivocally does not have currying or partial application, simply because Java 8 still does not have first class functions. What Java 8 has are compiler-synthetic lambdas that are generated (via fancy invokedynamic static method lambda meta factory generation trickery) into functional interface objects.

So really, when you get down to the core of things, you’re still dealing with objects, and anything you can do with objects hasn’t really changed, other than a lot of syntactic sugar and some performance benefits as compared to spinning a bunch of anonymous inner classes.

However, from a practical standpoint, the answer is more like “maybe” or “kind-of”.

Keep in mind that at the core of Java’s lambda support is the translation of a lambda into a functional interface. Assuming you know the functional interfaces you’re dealing with (such as the standard java.util.function interfaces), then you can create some reusable utilities that can help. For example, consider partial application using a BiFunction example. We can partially apply parameters by hand:

1BiFunction<Integer,Integer,Integer> adder = (a,b) -> a + b;
2Function<Integer,Integer> addOne = (b) -> adder.apply(1, b);

All we’ve effectively done here is create an adapter object around the initial functional object; but in practice it is indeed partial application. You could also make this partial application a utility:

1public static <A,B,R> Function<B,R> partial(BiFunction<A,B,R> func, A aVal) {
2	return (b) -> return func.apply(aVal, b);
3}
4
5BiFunction<Integer,Integer,Integer> adder = (a,b) -> a + b;
6Function<Integer,Integer> addOne = partial(adder, 1);

From this viewpoint, currying is also “practically” possible, although the verbose type signatures can make it less than ideal, as the curried nature of the value is quite explicit in the typing. Consider our curried add:

1Function<Integer,Function<Integer,Integer>> add = (a) -> (b) -> a + b;

Here we’ve defined a curried add function. We can partially apply as before:

1Function<Integer,Integer> addOne = add.apply(1);
2addOne.apply(2); // returns 3
3addOne.apply(3); // returns 4

The Problems with Generalizing

One of the strengths of true functional currying and partial application is that it can be done in a very general way. Since functions are a core “currency” of the language, you can effectively take any function and curry it into a decomposed chain of functions, allowing you to pass those parts around. Ideally in Java, you could take a three parameter function and turn it into a 3-deep single parameter function chain, but, in practice it’s a lot more sketchy.

It’s worth considering that in Java a “function” is really defined via the implementation of a particular interface (with Java 8 shipping specific “standard” implementations), and despite having a standard library, it’s also meant to bridge the compatibility gap with existing libraries that existed before Java 8, so you can have a lambda become an implementation of any SAM interface (single abstract method).

Once you bake a lambda into one of these interface implementations, you kind of lose the “general” nature of it, and it becomes a specific (and opaque) thing; even if that thing is semantically identical to another thing.

This is quite relevant looking at Google Guava. Guava ships a small suite of functional programming tools, and is very common in many Java projects active today. Most of these functional APIs are superceded by Java 8, but replacing them will be a gradual process for a lot of teams.

For example, Guava has a Function interface. While there are some extra bits in Java 8, at its core, the Google and Java Function interfaces are of parity:

1// Guava
2public interface Function<F,T> {
3	T apply(F param);
4}
5
6// Java 8
7public interface Function<F,T> {
8	T apply(F param);
9}

Now - consider this Guava-interfacing code on Java 8 (using Guava’s Iterables utility class):

1List<Integer> ints = Arrays.asList(1,2,3);
2Iterable<String> strings = Iterables.transform(ints, Integer::toString);

Internally, what Java has actually done here (Java-7-style) can be thought of like this:

1List<Integer> ints = Arrays.asList(1,2,3);
2Iterable<String> strings = Iterables.transform(ints, new com.google.common.base.Function<Integer,String>() {
3  public String apply(Integer x) {
4    return x.toString();
5  }
6});

You’ll get a compile time error if you try and use a standard type intermediately (I’ve left explicit packages in the code for clarity):

1java.util.function.Function<Integer,String> func = Integer::toString;
2com.google.common.base.Function<Integer,String> googFunc = Integer::toString;
3
4// OK:
5Iterable<String> strings = Iterables.transform(ints, googFunc);
6// Compile-time error:
7strings = Iterables.transform(ints, func);

Thankfully, this mismatch can easily be resolved in code by declaring the lambda as the correct type as I illustrated, or by adapting it through using something like a method reference:

1// Construct (or receive) the wrong type
2java.util.function.Function<Integer,String> func = Integer::toString;
3// Use a method reference to adapt the wrong type into the right type via a lambda.
4Iterable<String> strings = Iterables.transform(ints, func::apply);

Here we’re actually creating a new functional wrapper of the “google” type around our core Java function using method references as the short-hand to do so.

However, because functions and their accepted parameters and type declarations are not a “universal” type in the language (at the same ubiquitous level as Object), there will unfortunately always be impedence mismatches of the sort seen above. This sort of friction that exists is practically easily to resolve in code as shown above, but will have a tendency to cause library log-jams as you try to use techniques like partial application and currying.

Concretely speaking, what happens when you want a three-parameter function? You could of course create your own interface for it:

1public interface TriFunction<A,B,C,D> {
2	public D apply(A a, B b, C c);
3}
4
5TriFunction<String,Integer,String,String> wat = (a,b,c) -> a + String.valueOf(b) + c;
6String result = wat.apply("test",5,"testagain"); // test5testagain

But this will not be recognized by other libraries. Or you could get fancy with currying:

1Function<String, Function<Integer, Function<String,String>>> spicy =
2	(a) -> (b) -> (c) -> a + String.valueOf(b) + c;
3String result = spicy.apply("test").apply(5).apply("testagain");

Unfortunately, this isn’t what I’d call idiomatic or friendly to most developers (Java or no), and still runs the issue that adapting through libraries will be bumpy depending on what they chose.

Summary

In-short, Java has the ability to generate, compose, and transform functional objects into different shapes in a far more concise syntax than before, but it’s still far more verbose and type-y than true functional counterparts (even Javascript as I illustrated here).

That doesn’t mean that Java isn’t orders of magnitude better of than it was; simply that it is still a good distance from (and probably never will be) a bastion of functional programming.

Understanding Method References

Java 8 introduces four types of method references:

  • Static - Converts any static method into a lambda with matching formal parameters.
  • Instance-Capturing - Converts a method call on a specific object into a lambda.
  • Constructor - Converts constructors into factory lambdas for a specific type.
  • Arbitrary Instance - Converts a method on all instances of a type into a lambda that accepts instances of that type.

Since method references apply more magic behind the scenes than straight lambdas, I thought it might be good to walk through each with examples from the pre-lamdba Java world on each:

Static

Static method references are probably the easiest to understand. For example, the method Integer.valueOf(String) can be converted into a Function<String,Integer>. Intuitively, that’s exactly what it is already - a context-less method that takes a String and returns an Integer.

Using the functional interfaces in java.util.function, we can illustrate the various ways to build a string to integer conversion function:

 1// The Java 7 way - wish this syntax a fond farewell!
 2Function<String,Integer> f1 = new Function<String,Integer>() {
 3  public Integer apply(String x) {
 4    return Integer.valueOf(x);
 5  }
 6};
 7
 8// The naive (and overly verbose) Java 8 way.
 9Function<String,Integer> f2 = (String str) -> {
10  return Integer.valueOf(str);
11};
12
13// The inference-y short-hand naive Java 8 way.
14Function<String,Integer> f3 = (str) -> Integer.valueOf(str);
15
16// The method reference Java 8 way.
17Function<String,Integer> f4 = Integer::valueOf

Instance-Capturing

Instance-capturing method references are, as the name implies, a way to capture instances in the enclosing type. Consider Integer.toString, which converts an integer instance back into a String:

 1Integer x = new Integer(123);
 2// Create a string supplier off of the instance Java 7 style.
 3Supplier<String> s1 = new Supplier<String>() {
 4  public String get() {
 5    return x.toString();
 6  }
 7}
 8
 9// Short-hand lambda version.
10Supplier<String> s2 = () -> x.toString();
11
12// Method reference version.
13Supplier<String> f2 = x::toString

In effect, the lambda closes over the variable and uses it later when evaluated, and that’s what the method reference is doing internally. We use a supplier in this case because we have no method parameters to toString(), and the instance is already known, so we can simply call the no-arg method to get the resultant value.

But what about an instance method that takes a parameter? That’s no problem, so long as the underlying type that the lambda is being coerced into accepts matching parameters.

So what does that mean? Let’s look at an example. String.indexOf(String). is an instance method on String that accepts a string, and returns an int. We can translate it into a Function like so:

1String str = "abcdefg";
2Function<String,Integer> indexOfFunc = str::indexOf
3Integer x = indexOfFunc.apply("abc"); // returns 0.
4x = indexOfFunc.apply("def"); // returns 3.
5// etc.

However, it’s worth noting that we can also go directly to primitives with Java 8, as there are primitive-friendly functional interfaces in the java.util.function package as well:

1ToIntFunction<String> indexOfFuncPrim = str::indexOf
2int x = indexOfFunc.applyAsInt("abc");

This avoids the boxing and type indirection, at the expense that the API is less generally reusable. There will be some interesting learning curves for API designers regarding whether to and how to properly flow primitive variants through their APIs.

It’s important to note here that the type inferencing implied by the assignment of the method reference is how Java will choose between overloaded methods as well. This is quite important for our next type of method reference.

Constructors

Constructor references are effectively shorthand for factories of Objects. These will go along way towards getting rid of the factory-hell in Java land that has been incurred in the name of making things “pluggable” and “flexible”.

 1Supplier<List<String>> listMaker = ArrayList::new;
 2// Calls new ArrayList<String>();
 3List<String> newList = listMaker.get();
 4
 5IntFunction<List<String>> sizedListMaker = ArrayList::new;
 6// Calls new ArrayList<String>(int) -- setting initial capacity.
 7List<String> newList2 = sizedListMaker.apply(5);
 8
 9// Same with boxed params using standard function interface:
10Function<Integer, List<String>> sizedMaker2 = ArrayList::new;
11List<String> newList3 = sizedMaker2.apply(10); // boxes to Integer.valueOf(10) to call.

Arbitrary-Instance

These types of method references are perhaps the most mind-bending when you first work with them, as they imply there is a magic instance somewhere they work against, however, once you understand the conversion into a lambda, they are quite straightforward.

The goal of an arbitrary instance method reference is to allow you to refer to a method on an instance that will be encountered at execution time. In the Java implementation, this means the instance will be the first argument of the lambda invocation (aka, passing in “self”), and the remainder of the parameters will be as encountered on the method itself.

Let’s walk through an example using Integer.toString() once again. This time the method reference produces a lambda that operates on the integer instance being passed in instead of capturing one in the current context:

 1// Java 7 implementation.
 2Function<Integer,String> f1 = new Function<Integer,String>() {
 3  public String apply(Integer x) {
 4    return x.toString();
 5  }
 6};
 7// Standard lambda.
 8Function<Integer,String> f2 = (x) -> x.toString();
 9
10// Method reference.
11Function<Integer,String> f3 = Integer::toString;

So, where-as our “instance-capturing” method reference produced a method signature with no parameters (aka Supplier's String get() method), our “arbitrary instance” method reference produces a method that still returns a String, but also accepts the instance to operate against; in this case as a Function with the method signature: String apply(Integer self).

Where this gets more interesting (and a little more confusing initially) is when you have methods that accept parameters. Consider our String.indexOf(int) case again. What does a String::indexOf method reference produce? If you remember the rule, the first parameter of the method signature will be our type, and the second-through-N will be the standard parameters of the method. While Java doesn’t ship a whole suite of arbitrarily tupled functional interfaces, it does have a BiFunction that accepts two parameters:

 1// Java 7 form.
 2BiFunction<String,String,Integer> bf1 = new BiFunction<String,String,Integer>() {
 3  public Integer apply(String self, String arg) {
 4    return self.indexOf(arg);
 5  }
 6};
 7
 8// Java 8 standard lambda.
 9BiFunction<String,String,Integer> bf2 = (str,i) -> str.indexOf(i);
10
11// Method reference:
12BiFunction<String,String,Integer> bf3 = String::indexOf;

Admittedly, these typed signatures are long-winded, but keep in mind that generally speaking you won’t see them directly; lambdas are most often declared directly at the call site. So instead you’d have something that would accept a BiFunction (or similar), making the syntax flow like this:

1factory.setIndexFinder(String::indexOf);
2
3// Signature of this method might look like this:
4public class SomethingFactory<T> {
5  public void setIndexFinder(BiFunction<T,String,Integer> finder) { ... }
6}

We can also go so far as to apply primitives in this case as well; Java does have a ToIntBiFunction that allows us to eliminate the boxing return value:

1ToIntBiFunction<String,String> bf = String::indexOf
2int x = bf.applyAsInt("abc", "c"); // returns 2.

The Increased Importance of Generic Exceptions in API Design

One of the more interesting things with Java 8 will be how it impacts the way API design is done. This is already being discussed a lot with lambdas, and indeed, they are the key driver for much of the API change. However, it’s not as simple as making sure you accept single method interfaces everywhere. There are a lot of subtle changes to consider. I will walk through one here with exceptions.

The ability to generically define the exceptions in a throws clause for a method in Java isn’t a new thing (although most devs don’t seem to know or care about it). Pop open any Java 7 project, and you’ll be able to do this:

 1public abstract class Thingy<T extends Throwable> {
 2  public void doSomething() throws T {
 3    // ...
 4  }
 5}
 6
 7public class FileThingy extends Thingy<FileNotFoundException> {
 8  @Override
 9  public void doSomething() throws FileNotFoundException {
10    // ...
11  }
12}

Unfortunately, in practical terms this is of limited value in most cases, as the context of handling the exception usually needs to know the explicit type, making the polymorphic benefits of generics somewhat minimal.

In fact, the only case I’ve ever had where this provided legitimate value was in tunneling typed exceptions through a transaction-handling method.

A Rare Useful Case Pre Java-8

 1public void saveThingy(Thingy thingy) throws NotFoundException, AlreadyExistsException, InvalidInputException {
 2  try {
 3    inTransaction(new TransactionalOp() {
 4      public void exec() throws Throwable {
 5        // may save, or may throw one of many checked exceptions.
 6        throw new AlreadyExistsException();
 7      }
 8    });
 9  }
10  catch(TransactionException e) {
11    e.throwIf(NotFoundException.class)
12     .or(AlreadyExistsException.class)
13     .or(InvalidInputException.class)
14     .elseRuntimeException();
15  }
16}
17
18// the signature of the generic "inTransaction" method:
19public void inTransaction(TransactionalOp op) throws TransactionException { ... }

In this case, we want our transactional op to be able to throw checked exceptions so our outer-method can declare them (and force API users to handle them), but we can’t go changing the signature of our reusable inTransaction method.

To handle a “general” exception bubbling workflow, The inTransaction method catches all Throwables, and wraps them in a new checked exception that can then be unraveled using this fairly clean and fluid API. Effectively, the entire goal of this is to make it easier to type than a whole bunch of if(e.getCause() instanceof XYZ) throw (XYZ)e.getCause(); switches.

The TransactionException implementation could look something like this:

 1public class TransactionException extends Exception {
 2  public TransactionException(Throwable cause) {
 3    super(cause);
 4  }
 5
 6  public <T extends Throwable> TransactionException throwIf(Class<T> type) throws T {
 7    if(type.isInstance(getCause())) throw type.cast(getCause());
 8      return this;
 9  }
10
11  public <T extends Throwable> TransactionException or(Class<T> type) throws T { return throwIf(type); }
12
13  public void elseRuntimeException() {
14    throw new RuntimeException(getCause());
15  }
16}

So, like I said - that’s the only time it’s really benefited me.

Coming Soon with Java 8: More Generic Exceptions

In Java 8 thanks to the utility and terse syntax of lambdas this generification of throws parameters is becoming much more useful, and is something you can start considering to assist developers in using your APIs. Consider, for example, the Java 8 Optional class:

1public void loadString() throws IOException {
2  Optional<String> maybeStr = // load from somewhere.
3  String str = maybeStr.orElseThrow(() -> new IOException());
4}

In this case, we’re asking the Optional to throw our custom exception (an IOException) if the String is not present. To support this flow, the optional class has a method that takes a supplier of exceptions of a certain type:

1public <E extends Throwable> T orElseThrow(Supplier<? extends E> supplier) throws E {
2  // effective impl:
3  if(get() != null) return get();
4  else throw supplier.get();
5}

Since you can specify an implementation of the exception supplier in a very brief lambda definition, this provides a very clear and concise flow, and makes orElseThrow fit your use case, instead of the typical scenario of checked exceptions, where you have to work around things to meet the need of the API that throws the exception.