I have a use case where pattern matching on opaque types when done via the unapply method of the companion would make a lot of sense. This is a use case where we do not want to pattern match on the underlying opaque object directly though. We only want to give users of the library a way to have a view on the opaque object that can be used in pattern matching.
The general use case comes to light when writing libraries that abstract between many different implementations of a particular standard or Mathematical abstraction.
In 2011 I discovered that Scala allows us to sidestep that whole problem and that one could write a library that would just abstract these differences, but without adding those indirection layers that end up being expensive in terms of memory and cpu.
The answer in Scala3 is to use Opaque Types, which amazingly ends up incurring no cost at all!
But there is a problem as we wish to design a developer friendly library, in that opaque types don’t allow pattern matching.
So if one looks at the test case:
bKt.asMatchable match case Triple(sub,URI(rel),obj) => assertEquals(sub,bbl)
we see two problems:
- I need to use
asMatchablefor the Triple.unapply to work
- The code won’t compile because it can’f find that URI is a matchable, i.e. it cannot find the URI.unapply
In both those cases I don’t want the unapply or pattern matching to give me the underlying structure of each of the libraries, the one hidden by the opaque keyword. Rather we want to be able to have a coherent view that is the same over all implementations. This would be given by the
unapply function in the companion objects.
So here we have an algebra of opaque data structures that fit together in a coherent way, and we want to abstract over the implementations so that people can write generic scala RDF code that will compile to use any of the 10 libraries mentioned and more. E.g. starting from a generic
class MyProgram[Rdf<:RDF](...) we should be able to produce one version for HP’s Jena
object ProgHp extends MyProgram[Jena] and one for IBM’s
object ProgIBM extends MyProgram[Rdf4J], etc…
I have written projects using banana-rdf that work just like that, and it is a real pleasure not to have to worry about implementation issues. That was written in Scala 2, used type projections, which were leaky (one could easily come to end up being confused with methods from the underlying types), and also did not work well with pattern matching. Now we have to rewrite them for Scala 3 and having pattern matching work correctly would make for a very good library.
PS. I hope this is the right forum to post this idea to.