More Scala + Hibernate

In a prior post on livejournal, I described a problem and partial solution to using Hibernate with Scala. When I left things, I said:

The only real downside to this is that it doesn't enforce that entities are used only in the context in which they were created. I'd love to find a way to solve this. I think it might be possible to recover this by parameterizing the entity types, binding the type parameter with a single unsafe-but-safe cast as they come out of the database, and then enforcing that the implicit Context parameter matches the type parameter. I'll have to experiment with this, although truth be told, I'm not sure this level of safety is worth the hassle.

So I've done this experiment.

Actually, it works very well. I was worried that many extra type annotations would be required, but with a couple of type aliases, things are pretty decent. So, now I declare each entity like:

class Project[C <: Context] { ... }

and I change each implicit parameter to C, e.g.,

def addPage(page: Page)(implicit context: C) { ... }

In my Context class, I declare several type aliases:

type Project = model.Project[this.type]

Then, as objects are pulled from the database, I just do

...asInstanceOf[Project]

on each, and since I have a context in scope, this is the correct (fully applied) type.

I was hoping this would be enough, but actually one final change is required. Unfortunately, it seems that Scala will not pass implicit values declared at a super-type of the declared parameter type. So now I need to say:

abstract class Parser {
  val context: Context
  implicit val _: context.type = context
  import context._
  ...
}

This is getting to be an unfortunate amount of boilerplate, but so far I'm still happy enough with this solution that I intend to pursue it and see how it scales.

A full example would probably help to make this much, much clearer. If I have time, I'll try to put something together. It's probably not clear just how amazingly great this is. It still seems almost like magic that the compiler is able to figure this stuff out. I get the most amazing amount of static safety, and it really feels like I get it for free.