1

I have created a number of different auction implementations in Scala using type classes and ad-hoc polymorphism.

An example of a Scala implementation can be found here.

In Scala one creates an instance of this auction as follows...

val google: GoogleStock = GoogleStock(tick=1)
val pricingRule = new MidPointPricingPolicy[GoogleStock]
val withDiscriminatoryPricing = OpenBidDoubleAuction.withDiscriminatoryPricing(pricingRule)

I would like users to be able to access the auction implementations from Java 8.

But I can not seem to figure out how to create an instance of an auction in Java. Taking this approach:

MidPointPricingPolicy<GoogleStock> midPointPricing = new MidPointPricingPolicy<GoogleStock>();
OpenBidDoubleAuction.DiscriminatoryPricingImpl<GoogleStock> auction = OpenBidDoubleAuction$.MODULE$.withDiscriminatoryPricing(midPointPricing);

works, but none of the type class contract methods are available. Specifically:

OpenBidDoubleAuction.DiscriminatoryPricingImpl<GoogleStock> auction2 = auction.insert(order3);

...yields the following compile error.

Error:(90, 82) java: cannot find symbol
symbol:   method insert(org.economicsl.auctions.singleunit.orders.LimitAskOrder<org.economicsl.auctions.GoogleStock>)
location: variable auction of type org.economicsl.auctions.singleunit.twosided.SealedBidDoubleAuction.UniformPricingImpl<org.economicsl.auctions.GoogleStock>

It seems that the Scala compiler generated contract methods for the type class are not available when the Java code is being compiled. In my build.sbt file I have set compileOrder := CompileOrder.ScalaThenJava in order to make sure that these Scala gets compiled first so that these methods would be available.

Based on a suggestion from @GhostCat I used javap to find out that the Scala compiler generates the following .class file...

OpenBidDoubleAuction$DiscriminatoryPricingImpl$$anon$1.class

which contains the byte code definitions of the relevant methods.

So I guess I need to know how can I access things defined in this byte code file from Java? Is it even possible?

2 Answers 2

3

The generic answer is: those are two different languages. The only things that are visible on the java side are the elements found in the bytecode for OpenBidDoubleAuction.

Thus: one potential way for you to figure "what can I use from Java": turn to javap and inspect the byte code generated by scalac. That will tell you about all available methods and their signatures. And if you find your "enhanced" example to be too complicated for that: step back. Create a minimal example - a small piece of scala; for which you then carefully analyze the generated byte code.

And of course: you first of all check the documentation - you want to avoid wasting your time on something that simply isn't possible. There are various language elements that you can't use from the Java side of things.

(please note: that link is outdated, but probably good enough as starting point for your own research)

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. Any ideas of what to look for in the byte code? Does the Scala compiler generate specific boilerplate in cases such as this? Perhaps compiler generates an anonymous class that contains the methods?
And just for the record: in case you solve this puzzle, it is always fine to put up a self answer (drop me a comment then, I am curious myself, too).
the "solution" that I have come up with at present is to create Java wrappers around the Scala code. Details are here if you are interested (scroll down towards the bottom to find the relevant bits). The wrappers are called JOpenBidDoubleAuction (or similar).
1

Java doesn't have the implicit keyword and doesn't know anything about implicits whatsoever. An implicit def to Java is just another method. So you'll have to add all the implicit conversions and implicit arguments explicitly when you call this code from Java. If you want to have an idea what that would look like, you can open up a Scala REPL and use the //print <tab> hint to see what your code would look like after a couple of desugarings and making implicits explicit.

For instance, given some typeclass Foo and implicit FooSyntax:

scala> 42.foo //print <tab>
   FooSyntax[Int](42)(Foo.fooInt).foo // : String

To be clear, where it says <tab> you have to press tab instead of typing it :)

Then if you're a bit lucky, all you have to do is convert that desugared Scala further into actual Java:

FooSyntax(42, Foo.fooInt()).foo();

If you're less lucky, you might have to add some extra MODULE$ stuff. If you're even less lucky and you have to interoperate with things like structural types or intersection types, then you might have to use reflection or casting respectively.

But in general: don't use Scala's advanced features like typeclasses if you want to call that same code from Java. If you have to create a library that is callable from Java, then try to write (in Scala) Java-friendly wrappers around the advanced/incompatible parts.

3 Comments

Glad some scala expert came by ;-)
Another approach would be to re-implement the type classes using F-bounded polymorphism correct? Would this approach be better than writing wrapper classes?
I guess it depends on your intentions. If you start out with writing a library that is specifically meant to be used from Java then you're probably best off only using features that interoperate well with Java, instead of patching on Java compatibility afterwards.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.