Scala: Variables containing types - scala

How would I write use a variable as a type? For example:
scala> class A
defined class A
scala> class B extends A
defined class B
scala> def convert[F, T](from: F): T = from.asInstanceOf[T]
convert: [F, T](from: F)T
scala> val b = new B
b: B = B#54038f36
scala> convert[B, A](b)
res18: A = B#54038f36
This works fine. But I am interested in doing:
scala> val aType = classOf[A]
aType: Class[A] = class A
scala> convert[B, aType](b)
<console>:12: error: not found: type aType
convert[B, aType](b)
How would I do this without initializing an object and using obj.type in there? I suspect that I need to use some reflection features (maybe TypeTag?), but I couldn't find out what the correct thing to use here.
Thanks!

Java's Class has a method cast which does exactly what you need:
val aType = classOf[A]
aType.cast(b)
Now as a method:
def convert[F,T](from: F, clazz: Class[T]) = clazz.cast(from)
And call:
convert(b, aType)

Related

Scala: TypeTag generated for an inner type inside a class doesn't match it's type

If a class contains an inner class and a TypeTag for it is generated inside this class the generated TypeTag will contain the inner type which is "relative to the container" and does not match the TypeTag's generic type parameter. E.g.:
scala> import scala.reflect.runtime.{universe => ru}
scala> class A { class B; val t = ru.typeTag[B] }
scala> val x = new A
scala> x.t
res0: reflect.runtime.universe.TypeTag[x.B] = TypeTag[A.this.B]
Here x.t is a TypeTag[x.B] but actually contains another type: A.this.B. The problem is that while the inner type is different for every instance of A, the type inside the TypeTag remains the same:
scala> val y = new A
scala> y.t
res1: reflect.runtime.universe.TypeTag[y.B] = TypeTag[A.this.B]
scala> x.t.tpe =:= y.t.tpe
res2: Boolean = true
scala> ru.typeOf[x.B] =:= ru.typeOf[y.B]
res3: Boolean = false
Is this behaviour intended by design or this issue could be resolved in later versions (my version is 2.11.7)?
One workaround for this problem is to generate the TypeTag outside the container class:
scala> def tt(a: A)(implicit t: ru.TypeTag[a.B]) = t
scala> tt(x)
res6: reflect.runtime.universe.TypeTag[x.B] = TypeTag[x.B]
scala> tt(y)
res7: reflect.runtime.universe.TypeTag[y.B] = TypeTag[y.B]
Are there any other workarounds?

Cast a variable to runtime type from existential typed TypeCast in Scala

This thread addressed how to use TypeTag to get runtime type of type parameters when used with Existential type. Another thread addressed how to cast a variable to its runtime type retrieved from TypeTag.
My question builds on the aforementioned threads (kind of a combination of the two scenarios). Parts of the code is duplicated from the two threads for clarity.
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> def cast[A](a: Any, tt: TypeTag[A]): A = a.asInstanceOf[A]
cast: [A](a: Any, tt: reflect.runtime.universe.TypeTag[A])A
scala> abstract class Animal[T](implicit tt: TypeTag[T]) {
| val ttag = tt
| }
defined class Animal
scala> case object Dog extends Animal[Int]
defined object Dog
scala> case object Cat extends Animal[String]
defined object Cat
scala> val aa: List[(Animal[_], Any)] = List((Dog, 5), (Cat, "stringgg"), (Dog, 2))
aa: List[(Animal[_], Any)] = List((Dog,5), (Cat,stringgg), (Dog,2))
scala> aa(0)._1.ttag
res25: reflect.runtime.universe.TypeTag[_] = TypeTag[Int]
scala> aa(1)._1.ttag
res26: reflect.runtime.universe.TypeTag[_] = TypeTag[String]
scala> cast(aa(0)._2, aa(0)._1.ttag)
res27: Any = 5
scala> cast(aa(1)._2, aa(1)._1.ttag)
res28: Any = stringgg
In short, the last two lines: cast(value, TypeTag[_]) always return a value of type Any. But my intention is to cast these values to the correct type stored in Dog|Cat.ttag, which, unfortunately, is not TypeTag[Int] or TypeTag[String] but TypeTag[_] due to usage of existential type. Is there any solution for it?
Edit 1:
Despite the field ttag is of type TypeTag[_], ttag.tpe does have the right "type" (but as an instance of reflect.runtime.universe.Type). Is it possible to use the typetag.tpe to cast to the right type?
You could change the cast method as,
def cast[A](a: Any, tt: TypeTag[_]): A = a.asInstanceOf[A] and
val x: Int = cast(aa(0)._2, aa(0)._1.ttag)
pair with path dependent type, you can type cast as following code shows:
import languageFeature.existentials
object TestExistential {
def main(args: Array[String]): Unit = {
val aa: Array[(Animal[T], T) forSome {type T}] = Array((Dog, 5:Integer), (Cat, "stringgg"), (Dog, 2:Integer))
aa.foreach(p=>{
val ani = p._1
val attr = p._2 // compiler weakness: existential type T is not unify with ani.castType
assert(ani.attrTyp.isAssignableFrom(attr.getClass))// because of boxing, real type is Integer not Int
assert(ani.clzTyp.isAssignableFrom(ani.getClass))
val typedAni:ani.castType = ani.asInstanceOf[ani.castType]
println(s"$typedAni of type Animal[${ani.attrTyp}] with $attr")
})
}
abstract class Animal[T]{
type castType = Animal[T]
val attrTyp: Class[T]
val clzTyp: Class[castType]
}
case object Dog extends Animal[Integer] {
override val attrTyp: Class[Integer] = classOf[Integer]
override val clzTyp: Class[Dog.castType] = classOf[Dog.castType]
}
case object Cat extends Animal[String] {
override val attrTyp: Class[String] = classOf[String]
override val clzTyp: Class[Cat.castType] = classOf[Cat.castType]
}
}
if typing in scala repl, you can see the reply:
scala> val typedAni:ani.castType = ani.asInstanceOf[ani.castType]
typedAni: ani.castType = Dog
scala> typedAni
res0: ani.castType = Dog

Explain "this.type" as a return type of various API methods

I am looking though the source code of the Promise[T] trait from the scala.concurrent package.
So here is the method declaration where I need your help in one place:
trait Promise[T] {
....
def complete(result: Try[T]): this.type =
if (tryComplete(result)) this else throw new IllegalStateException("Promise already completed.")
....
}
I do not really understand how to interpret the this.type as a complete method return type. Why not simple the return type could be Promise[T] ?
Sorry if my question will seem too simple for someone, I am just learning this stuff.
this.type is necessary in a path dependent context:
scala> class A { class B; def f(b: B): A = this }
defined class A
scala> val a1 = new A; val b1 = new a1.B; val a2 = new A
a1: A = A#721f1edb
b1: a1.B = A$B#5922f665
a2: A = A#65e8e9b
scala> a1.f(b1)
res6: A = A#721f1edb
scala> a2.f(b1)
<console>:12: error: type mismatch;
found : a1.B
required: a2.B
a2.f(b1)
^
Path dependent means that the compiler knows that types belong together. In the above example one can see that new a1.B produces a value of type a1.B and not only B. However, this does not work:
scala> a1.f(b1).f(b1)
<console>:11: error: type mismatch;
found : a1.B
required: _2.B where val _2: A
a1.f(b1).f(b1)
^
The problem is that the return type of f is A, which has no information anymore about the path dependent relationship. Returning this.type instead tells the compiler that the return type fulfills this relationship:
scala> class A { class B; def f(b: B): this.type = this }
defined class A
scala> val a1 = new A; val b1 = new a1.B; val a2 = new A
a1: A = A#60c40d9c
b1: a1.B = A$B#6759ae65
a2: A = A#30c89de5
scala> a1.f(b1).f(b1)
res10: a1.type = A#60c40d9c
I suspect the reason is supporting inheritance.
Consider this simple example
trait Foo[A] {
def foo: Foo[A] = this
}
trait Bar[A] extends Foo[A]
Now let's try it out
scala> (new Foo[Int]{}).foo
res0: Foo[Int] = $anon$1#7f0aa670
scala> (new Bar[Int]{}).foo
res1: Foo[Int] = $anon$1#4ee2dd22
As you can see, the method foo returns a Foo[Int] in both cases, and that's because you returned the "hardcoded" type Foo[T] in the method definition.
If you instead do
trait Foo[A] {
def foo: this.type = this
}
trait Bar[A] extends Foo[A]
then the returned type depends on the instance you're invoking foo on:
scala> (new Foo[Int]{}).foo
res2: Foo[Int] = $anon$1#1391e025
scala> (new Bar[Int]{}).foo
res3: Bar[Int] = $anon$1#4142991e

Implicits using structural types

What is a convenient way to use implicit values that are simple types? Ideally, I would like to do something like this:
scala> :paste
// Entering paste mode (ctrl-D to finish)
type A = String
type B = String
implicit val a: A = "a"
implicit val b: B = "b"
def c(implicit ab: A) = println(ab)
// Exiting paste mode, now interpreting.
defined type alias A
defined type alias B
a: A = a
b: B = b
c: (implicit ab: A)Unit
scala> c
<console>:13: error: ambiguous implicit values:
both value a in object $iw of type => A
and value b in object $iw of type => B
match expected type A
One can't subclass final case classes like String or Long either
scala> class C extends String
<console>:11: error: illegal inheritance from final class String
class C extends String
While Tim is correct, his approach would create a wrapper around the string and thus introduce runtime overhead. We can let the compiler do all this without the need to create new objects with a technique called type tagging. Following code is shamelessly taken from the shapeless source:
trait Tagged[U]
type ##[+T, U] = T with Tagged[U]
class Tagger[U] {
def apply[T](t : T) : T ## U = t.asInstanceOf[T ## U]
}
def tag[U] = new Tagger[U]
With those definitions you can write the following:
trait A
trait B
implicit def a: String ## A = tag[A]("foo")
implicit def b: String ## B = tag[B]("bar")
def foo(implicit a: String ## A) = a.toString
def bar(implicit b: String ## B) = b.toString
scala> foo
res21: String = foo
scala> bar
res22: String = bar
When you use "type" you're defining an alias for a type, not an actual new type.
What you want to do is define an actual new type.
case class A(a: String)
case class B(b: String)
implicit val a = A("a")
implicit val b = B("b")
def c(implicit ab: A) = println(ab.a)

Why can't the first parameter list of a class be implicit?

scala> class A(implicit a: Int);
defined class A
scala> class B()(implicit a: Int);
defined class B
scala> new A()(1)
res1: A = A#159d450
scala> new B()(1)
res2: B = B#171f735
scala> new A(1)
<console>:7: error: too many arguments for constructor A: ()(implicit a: Int)A
new A(1)
Why does Scalac insert an empty parameter list before the implicit parameter list provided in the class declaration?
This seems to be a feature, not a bug, judging by the commentary in the scalac sources:
// convert (implicit ... ) to
()(implicit ... ) if its the only
parameter section
I'm curious to know why this is done. I find it rather surprising.
The way I see it is that implicit parameter list does not replace the regular one(s). Since for constructor definitions at least one parameter list is needed, if nothing is indicated explicitly '()' is generated.
While this might be indeed puzzling, it's in line with generating an empty constructor when no parameter lists at all are present.
Okay, with the help of #venechka's answer, I think I've figured it out.
With ordinary classes, Scala infers and empty parameter list, either at the class declaration (class B), or at the point of class instantiation (new A and new B):
scala> class A()
defined class A
scala> new A
res19: A = A#12cdd20
scala> new A()
res20: A = A#1c37b8f
scala> class B
defined class B
scala> new B
res21: B = B#12801c5
scala> new B()
res22: B = B#79a340
So to be in keeping with this principle, it infers an empty parameter list before an implicit parameter list (class D(implicit ...)).
scala> class C()(implicit a: Int = 0)
defined class C
scala> new C
res23: C = C#9d1714
scala> new C()
res24: C = C#b38dba
scala> new C()(0)
res25: C = C#1677979
scala> class D(implicit a: Int = 0)
defined class D
scala> new D
res26: D = D#1a0d111
scala> new D()
res27: D = D#14e3372
scala> new D()(0)
res28: D = D#1609872