Partial Application of Type Parameters in Scala

bpholt's picture

Scala doesn’t directly support partial application of type parameters, which can be frustrating when several are required but only a portion can be inferred by the compiler. For example, this implicit class wraps a request object from the Amazon Java SDK and defines a method that accepts an asynchronous function that should be used to execute the request. (This provides a more fluent Scala API than using the Java SDK directly.)

Since the effect type F is not bound anywhere else, it cannot be inferred. I would like to provide just the type of F and let the compiler infer Req and Res. Unfortunately, since Scala doesn’t support partial application of type parameters, the caller has to explicitly provide all three types.

There is a workaround. One can wrap the function in a class paramterized by the unknown types, define an apply() method on the class that is parameterized by the inferrable types, and provide a function returning a new instance of the class. (The details are more fully explained in this blog post by Tony Morris.)

This raises another problem here, though. The : Effect part of the type parameter F[_] : Effect is syntactic sugar for an implicit parameter of the type Effect[F]. Since it’s defined on the class, the implicit parameter is added to the constructor, and therefore needs to be available to the helper function, too.

As a result, the syntax we want does not compile.

Luckily, there’s is a straightforward (although not immediately obvious, at least to me) solution. The trick is that the Effect[F] doesn’t need to be available throughout the wrapper class, only within the apply method. So, desugar it and move it to an implicit parameter to the method itself!

With the implicit RequestHolder in scope, callers can now call req.executeVia[IO](func) and the compiler does the rest!

It seems obvious now, but I kept coming back to this several times over the course of several weeks before the solution finally revealed itself. Hopefully this post will save someone else the trouble!

This post was inspired by my work at Dwolla, but the opinions expressed are my own. If you'd like to work on similar problems with smart, friendly, and inclusive people, we're hiring!