Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resolving a `Manifest` for a type with a type member

I am having trouble resolving a scala.reflect.Manifest for a type with a type member.

For example,

import scala.reflect.Manifest

trait Foo {
  type T
}

trait Bar[T]

object Main extends App {

  val barM: Manifest[Bar[Int]] =
    implicitly[Manifest[Bar[Int]]]

  val fooM: Manifest[Foo{type T = Int}] =
    implicitly[Manifest[Foo{type T = Int}]]

}

The above code does not compile, giving the following error.

Foo.scala:15: error: type mismatch;
 found   : scala.reflect.Manifest[Foo]
 required: scala.reflect.Manifest[Foo{type T = Int}]
Note: Foo >: Foo{type T = Int}, but trait Manifest is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: Foo{type T = Int}`. (SLS 3.2.10)
    implicitly[Manifest[Foo{type T = Int}]]
              ^
one error found

But the barM declaration works just fine.

I am aware that type members are not quite type parameters, but I am definitely not up on all the subtleties.

How can one go about resolving a Manifest for a type with a concrete type member?

like image 962
isomarcte Avatar asked Jan 28 '26 14:01

isomarcte


1 Answers

Structural types are not supported by Manifest. SI-4252 (Manifest of structural types) is labelled as "won't fix", and it is recommended that you use TypeTag instead. Manifest is also likely to be deprecated soon.

scala> import scala.reflect.runtime.universe.TypeTag
import scala.reflect.runtime.universe.TypeTag

scala> implicitly[TypeTag[Foo { type T = Int} ]]
res18: reflect.runtime.universe.TypeTag[Foo{type T = Int}] = TypeTag[Foo{type T = Int}]

You might also be able to work around this with a type alias, but it's hard to tell without a use-case.

scala> type FooAux[T] = Foo { type T }
defined type alias FooAux

// Compiles, but is it useful?
scala> implicitly[Manifest[FooAux[Int]]]
res19: scala.reflect.Manifest[FooAux[Int]] = Foo
like image 79
Michael Zajac Avatar answered Jan 30 '26 08:01

Michael Zajac