so

Generics in Scala

Volume 3, Issue 13; 04 Apr 2019

The intersection of Java generics and Scala is…not going well for me.

I freely admit to being a little out of my depth here. My formal training in type systems is a good few decades behind me. I’ve used generics in Java rather trivially once or twice, but they’re not something about which I can claim to have a deep and thorough understanding. I’m also a relative newcomer to Scala, so I’m not claiming a deep or thorough understanding of its type system either.

I set out this evening to update my XML Calabash v2 implementation, written in Scala (2.12 today) to use Saxon 9.9. Saxon 9.9 introduces generics in a number of places. Fine by me. I can cope, I imagine.

Except, I can’t apparently.

The stumbling block is trying to implement a class that extends the ExtensionFunctionDefinition class.Saxonica don’t appear to publish versioned APIs, so if you’re reading this much after 3 April 2019, take what you find at those pages with a grain of salt. It has an inner class that extends the ExtensionFunctionCall class. That, in turn, has an abstract method, call, defined thusly in Java:

public abstract Sequence<?> call(
    XPathContext context,
    Sequence[] arguments
)

My first attempt to define this in Scala was:

override def call(
    context: XPathContext,
    arguments: Array[Sequence]
): Sequence[_]

but that doesn’t compile: “trait Sequence takes type parameters”. For my second attempt, I tried:

override def call(
    context: XPathContext,
    arguments: Array[Sequence[_]]
): Sequence[_]

But that, I’m told, doesn’t override anything. Hark, the compiler says: [error] (Note that Array[net.sf.saxon.om.Sequence] does not match Array[net.sf.saxon.om.Sequence[_]]: their type parameters differ)

And here we seem to be at an impasse. I can just implement the damned thing in Java, of course, but is this an actual limitation in Scala or in my understanding?

I was lying before, by the way, about my first attempt. My first attempt was actually:

override def call(
    context: XPathContext,
    arguments: Array[Sequence[_ <: Item[_ <: Item[_]]]]
): Sequence[_ <: Item[_ <: Item[_]]]

which I crafted by bluntly copying Java into Scala and letting IntelliJ IDEA translate it. I had failed to work out what to do with the recursive nature of the Item declaration.

Update 4 Apr 2019: When the answer failed to turn up on Twitter in a timely fashion, I decided to ask stackoverflow which is probably what I should have done in the first place.

Update 13 Apr 2019: In the end, I punted and wrote Java shims that call Scala implementations. It may not be pretty, but it works.