tags:

views:

385

answers:

2

Since Scala 2.7.2 there is something called Manifest which is a workaround for Java's type erasure.

But how does Manifest work exactly and why / when do you need to use it?

This blog post by Jorge Ortiz explains some of it, but it doesn't explain how to use it together with context bounds.

Also, what is ClassManifest, what's the difference with Manifest?

I have some code (part of a larger program, can't easily include it here) that has some warnings with regard to type erasure; I suspect I can solve these by using manifests, but I'm not sure exactly how.

+10  A: 

Not a complete answer, but regarding the difference between Manifest and ClassManifest, you can find an example in the Scala 2.8 Array paper:

The only remaining question is how to implement generic array creation. Unlike Java, Scala allows an instance creation new Array[T] where T is a type parameter. How can this be implemented, given the fact that there does not exist a uniform array representation in Java?

The only way to do this is to require additional runtime information which describes the type T. Scala 2.8 has a new mechanism for this, which is called a Manifest. An object of type Manifest[T] provides complete information about the type T.
Manifest values are typically passed in implicit parameters; and the compiler knows how to construct them for statically known types T.

There exists also a weaker form named ClassManifest which can be constructed from knowing just the top-level class of a type, without necessarily knowing all its argument types.
It is this type of runtime information that’s required for array creation.

Example:

One needs to provide this information by passing a ClassManifest[T] into the method as an implicit parameter:

def  tabulate[T](len:Int,  f:Int=>T)(implicit m:ClassManifest[T]) =  { 
  val  xs  =  new  Array[T](len) 
  for   (i  <- 0  until   len)  xs(i)   = f(i) 
  xs 
} 

As a shorthand form, a context bound1 can be used on the type parameter T instead,

(See this SO question for illustration)

, giving:

def  tabulate[T:    ClassManifest](len:Int,  f:Int=>T)  =  { 
  val  xs  =  new  Array[T](len) 
  for   (i  <- 0  until   len)  xs(i)   = f(i) 
  xs 
} 

When calling tabulate on a type such as Int, or String, or List[T], the Scala compiler can create a class manifest to pass as implicit argument to tabulate.

VonC
+19  A: 

The compiler knows more information about types than the JVM runtime can easily represent. A Manifest is a way for the compiler to send an inter-dimensional message to the code at runtime about the type information that was lost.

This is similar to how the Kleptonians have left encoded messages in fossil records and the "junk" DNA of humans. Due to limitations of lightspeed and gravitational resonance fields, they are unable to communicate directly. But, if you know how to tune into their signal, you can benefit in ways you cannot imagine, from deciding what to eat for lunch or which lotto number to play.

It isn't clear if a Manifest would benefit the errors you are seeing without knowing more detail.

One common use of Manifests is to have your code behave differently based on the static type of a collection. For example, what if you wanted to treat a List[String] differently from other types of a List:

 def foo[T](x: List[T])(implicit m: Manifest[T]) = {
    if (m <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }

  foo(List("one", "two")) // Hey, this list is full of strings
  foo(List(1, 2)) // Non-stringy list
  foo(List("one", 2)) // Non-stringy list

A reflection-based solution to this would probably involve inspecting each element of the list.

A context bound seems most suited to using type-classes in scala, and is well explained here by Debasish Ghosh: http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

Context bounds can also just make the method signatures more readable. For example, the above function could be re-written using context bounds like so:

  def foo[T: Manifest](x: List[T]) = {
    if (manifest[T] <:< manifest[String])
      println("Hey, this list is full of strings")
    else
      println("Non-stringy list")
  }
Mitch Blevins
Upvoted for the use case. Wish I had a second vote for the out-of-left-field Kleptonian section.
huynhjl
Aha, it's a secret interdimensional message from the Scala compiler... ;-)
Jesper