views:

256

answers:

1

I've got this code that works:

  def testTypeSpecialization: String = {
    class Foo[T]

    def add[T](obj: Foo[T]): Foo[T] =  obj

    def addInt[X <% Foo[Int]](obj: X): X = { 
      add(obj)
      obj
    }

    val foo = addInt(new Foo[Int] {
      def someMethod: String = "Hello world"
    })

    foo.someMethod
  }

But, I'd like to write it like this:

 def testTypeSpecialization: String = {
    class Foo[T]

    def add[X, T <% Foo[X](obj: T): T =  obj

    val foo = add(new Foo[Int] {
      def someMethod: String = "Hello world"
    })

    foo.someMethod
  }

This second one fails to compile:

no implicit argument matching parameter type (Foo[Int]{ ... }) => Foo[Nothing] was found.

Basically:

  • I'd like to create a new anonymous class/instance on the fly (e.g. new Foo[Int] { ... } ), and pass it into an "add" method which will add it to a list, and then return it
  • The key thing here is that the variable from "val foo = " I'd like
    its type to be the anonymous class, not Foo[Int], since it adds methods
    (someMethod in this example)

Any ideas?

I think the 2nd one fails because the type Int is being erased. I can apparently 'hint' the compiler like this: (this works, but seems like a hack)

  def testTypeSpecialization = {
    class Foo[T]

    def add[X, T <% Foo[X]](dummy: X, obj: T): T =  obj

    val foo = add(2, new Foo[Int] {
      def someMethod: String = "Hello world"
    })

    foo.someMethod
  }
+1  A: 

Dario suggested making T covariant in Foo:

def testTypeSpecialization: String = {
    class Foo[+T] {
      var _val: Option[T]
    } 

    def add[X, T <% Foo[X](obj: T): T =  obj

    val foo = add(new Foo[Int] {
      def someMethod: String = "Hello world"
    })

    foo.someMethod
  }

But, with this adds too many restrictions to Foo it seems, e.g. I can't have a var member variable of type Option[T].

covariant type T occurs in contravariant position in type Option[T] of parameter of setter val=

Alex Black