3

I'm trying to use Scala's manifests to instantiate a type, and I'm running into problems when that type is parameterized on types with a view bound. I've distilled the problem down to the following code:

class foo[X <% Ordered[X]]() {}

def boo[T](implicit m : Manifest[T]) = { m.erasure.newInstance().asInstanceOf[T] }

boo[foo[String]]

java.lang.InstantiationException: foo
    at java.lang.Class.newInstance0(Class.java:357)
    at java.lang.Class.newInstance(Class.java:325)
    . . .

So you can see we have a simple class, foo, which is parameterized on X; which is view bounded by Ordered[X]. The boo function simply attempts to instantiate a new instance of a foo[String] using manifests. However, when this function is called, things go horribly awry and I get the stack trace that begins as I have shown. When the type parameter of foo is not view bounded, the instantiation works without issue. I assume this has something to do with the fact that the view bound is just syntactic sugar for the existence of an implicit conversion of X => Ordered[X], and that somehow the manifest being dependent on another manifest is causing a problem. However, I have no idea what's really happening or, more importantly, how to fix it. Is this even possible in Scala, and if not, how do people achieve something similar?

nomad
  • 1,809
  • 2
  • 18
  • 33

2 Answers2

7

newInstance works only if T has a parameterless constructor. foo has not. The view bound <% (just as a the context bound :) is a shortcut for an implicit parameter in the constructor.

class foo[X <% Ordered[X]] is the same as class foo(implicit freshName: X => Ordered[X]). Lacking a parameterless constructor for foo, newInstance fails.

Didier Dupont
  • 29,398
  • 7
  • 71
  • 90
5

You could make it work the following way:

def boo[A, B[_]](implicit toOrdA: A => Ordered[A], mf: Manifest[B[A]]): B[A] = {
  val constructor = mf.erasure.getConstructor(classOf[A => Ordered[A]])
  constructor.newInstance(toOrdA).asInstanceOf[B[A]]
}
Heiko Seeberger
  • 3,702
  • 21
  • 20
  • Thanks Heiko! There was some other additional strangeness going on with the type bounds in my case (not shown in this trivial example), but after I worked that out, your solution worked great! – nomad May 12 '12 at 03:27