Hi,
I have the following trait:
sealed trait Val[V] {
val v: V
}
I create instances of these implicitly using this definition:
implicit def pack[A](s:A) : Val[A] = new Val[A] {
println(s"Packing $s")
override val v: A = s
}
for example I can do the following:
val r5: Val[String] = "100"
println(s"r5: Val(${r5.v}) : ${r5.v.getClass}")
val r6: Val[Double] = 200.0
println(s"r6: Val(${r6.v}) : ${r6.v.getClass}")
val r7: Val[Array[Double]] = Array(300.0, 301, 302)
println(s"r7: Val(${r7.v.mkString(",")}) : ${r7.v.getClass}")
I can store these values so:
val rs = Map("x" -> r5, "y" -> r6, "z" -> r7)
println(s"rs = $rs")
val s5 = rs("x")
val s6 = rs("y")
val s7 = rs("z")
I now want to unpack the value using these definitions:
def test[A,B](av: Val[A], f: A => B)(implicit a: Val[A] => Either[String,A]): Either[String,B] = {
a(av).flatMap( e => Right(f(e)) )
}
implicit def unpack[T](t:Val[_]): Either[String,T] = {
try {
val v = t.v.asInstanceOf[T]
Right(v)
} catch {
// When used via implicits should never reach this
case e:Exception => Left(e.getMessage)
}
}
If I use the instances that have their types known at compile time, I can do this:
val u0 = test(r5, (e:String) => e.toInt)
val u1 = test(r6, (e:Double) => e)
val u2 = test(r7, (e:Array[Double]) => e)
println(u0)
println(u1)
println(u2)
However, If I do the following:
val v0 = test(s5, (e:String) => e.toInt)
val v1 = test(s6, (e:Double) => e)
val v2 = test(s7, (e:Array[Double]) => e)
println(v0)
println(v1)
println(v2)
I get compilation errors: For example:
[error] AutoVal.scala:149: type mismatch;
[error] found : String => Int
[error] required: _1 => Int where type _1 >: Array[Double] with Double with String
[error] val v0 = test(s5, (e:String) => e.toInt)
[error] ^
Which is not what I expected. I assumed that the type of the first parameter of the
anonymous function in test
is fully defined and it should there be enough to set
the type T
in unpack
. However the String
in the error message above does not
impose the type of _1
.
So my questions are: why is this not so and is there a way for one “force” this?
TIA