Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's Scala's OptManifest and NoManifest for?

I'm learning Scala's concept of manifests and I have a basic understanding how to use it in some simple cases. What puzzles me is what's OptNanifest and NoManifest for? I've never seen then used. Can someone give an example where they're are needed/useful?

(I see that Scala 2.10 replaces the concept of Manifests with TypeTags but until 2.10 is final we have to use Manifests.)

like image 801
Petr Avatar asked Sep 29 '12 09:09

Petr


1 Answers

Suppose we have the following case class and type alias:

scala> case class Foo[A](a: A)
defined class Foo

scala> type F = Foo[_]
defined type alias F

We can now (not very usefully) make a list of things of type F:

scala> val foos: List[F] = List(Foo(1), Foo("a"), Foo('a))
foos: List[F] = List(Foo(1), Foo(a), Foo('a))

And we can turn this into an array:

scala> foos.toArray
res0: Array[F] = Array(Foo(1), Foo(a), Foo('a))

So clearly the compiler is able to find the manifest it needs as an implicit argument to the toArray method on List. But if we ask for a plain old Manifest for F, we get an error:

scala> manifest[F]
<console>:11: error: overloaded method value classType with alternatives:
  (prefix: scala.reflect.Manifest[_],clazz: Class[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and>
  (clazz: Class[F],arg1: scala.reflect.Manifest[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and>
  (clazz: Class[_])scala.reflect.Manifest[F]
 cannot be applied to (java.lang.Class[Foo[_$1]], scala.reflect.Manifest[_$1])
              manifest[F]

So it's clear that the compiler is having trouble using manifests to represent the wildcard in our type alias.

The reason toArray works is that it expects a ClassManifest, not just a Manifest. And in fact we can get a ClassManifest for F with no problems, precisely because ClassManifest uses OptManifest to represent its type arguments—unlike Manifest, whose type arguments are just other things of type Manifest.

scala> classManifest[F]
res2: ClassManifest[F] = Foo[<?>]

That <?> is the string representation of NoManifest. It plays the role of None here, allowing the compiler to represent the class information about the type F (which is all we need for creating an array, fortunately), without saying anything about the type arguments of F beyond "no, I can't model that".

like image 190
Travis Brown Avatar answered Nov 15 '22 07:11

Travis Brown