Trait runtime type of type parameter through TypeTag when used with Existential type in Scala -


i have trait type parameter. runtime type use typetag. however, when trait (and classes) used existential type in collection, e.g. list or map, typetag "lost".

here example of standard way use type tag:

scala> import scala.reflect.runtime.universe._ import scala.reflect.runtime.universe._  scala> trait animal[t] {      |   def typet()(implicit t: typetag[t]) = t.tpe      | } defined trait animal  scala>   scala> class dog extends animal[int]  defined class dog  scala> class cat extends animal[string]  defined class cat  scala>   scala> val dog = new dog  dog: dog = dog@4aa88c93  scala> val cat = new cat  cat: cat = cat@2281e252  scala> dog.typet res46: reflect.runtime.universe.type = int  scala> cat.typet res47: reflect.runtime.universe.type = string 

as can see, far good, method typet defined , implemented in trait animal works. however, when used list , existential types, failed working:

scala> val aa: list[animal[_]] = list(dog, cat, dog) aa: list[animal[_]] = list(dog@4aa88c93, cat@2281e252, dog@4aa88c93)  scala> aa(0).typet res52: reflect.runtime.universe.type = _$1  scala> aa(1).typet res53: reflect.runtime.universe.type = _$1 

explicit casting (like following) sure worked. of time given list[anima[_]]. if level of typecast necessary, , how?

scala> aa(0) res55: animal[_] = dog@4aa88c93  scala> aa(0).asinstanceof[dog] res56: dog = dog@4aa88c93  scala> aa(0).asinstanceof[dog].typet res57: reflect.runtime.universe.type = int 

i understand aa(0) animal[_] reason. still, aa(0) not animal[_], dog. why typet (or typetag) not used if normal method?

the problem here typet() method, return different value depending on knowledge of animal. if compiler can prove have animal[int], can typetag[int]. existential type in list[animal[_]], lose type information contained in animal. when select arbitrary element list, know it's animal[_] when typet called, , nothing else. typet not know type parameter t each instance. has no way of proving in context.

the type cast of course works, because asinstanceof[animal[cat]] tells compiler forget knows. if course can throw classcastexception when wrong.

one way can work requiring implicit typetag[t] on instantiation of animal[t], , storing value, rather resolving within method. unfortunately, means cannot use trait.

abstract class animal[t](implicit tt: typetag[t]) {     val tpe = tt.tpe }  class dog extends animal[int] class cat extends animal[string] val dog = new dog val cat = new cat  scala> val aa: list[animal[_]] = list(cat, dog, cat) aa: list[animal[_]] = list(cat@5a9faacf, dog@675c379d, cat@5a9faacf)  scala> aa(0).tpe res6: reflect.runtime.universe.type = string  scala> aa(1).tpe res7: reflect.runtime.universe.type = int 

alternatively, express using little syntactic sugar on implicit parameters:

abstract class animal[t: typetag] {     val tpe = implicitly[typetag[t]].tpe } 

Comments

Popular posts from this blog

cakephp - simple blog with croogo -

How to group boxplot outliers in gnuplot -

bash - Performing variable substitution in a string -