I'd like to do some calculation on type level during runtime. So I define wrapper classes and implicit definitions for them. But I could not understand why type information is lost during computation
sealed trait Solve[In] {
type Out
}
implicit def idSolve[I] = new Solve[I] {
override type Out = I
}
type X = Int
val y = implicitly[Solve[X]]
val e = implicitly[X =:= y.Out]
val l = implicitly[X <:< y.Out]
val g = implicitly[y.Out <:< X]
The compiler accepts neither of e
, l
, g
:
TypeSolution.scala:15: error: Cannot prove that test.Test.X =:= test.Test.y.Out.
val e = implicitly[X =:= y.Out]
^
TypeSolution.scala:16: error: Cannot prove that test.Test.X <:< test.Test.y.Out.
val l = implicitly[X <:< y.Out]
^
TypeSolution.scala:17: error: Cannot prove that test.Test.y.Out <:< test.Test.X.
val g = implicitly[y.Out <:< X]
^
three errors found
What is going on and why compiler refuses to admit that X
and y.Out
are the same types. Is it possible to rephrase the example so it would compile?
implicitly
"forgets" type information, as per it's definition (+ inferred types % renaming):Note that it returns something of type
A
, nota.type
. Therefore, your code looks like:y
's type is inferred toSolve[Int]
, notSolve[Int] { type Out = Int }
, soy.Out
is unknown.You can define a custom
implicitly
without this restriction:Which works as a drop-in replacement:
Sidenote:
Won't work, because Scala doesn't like it when you use singleton types without an
AnyRef
upper bound.Works in this case, but it won't allow
AnyVal
subclasses or the like. However, the macro solution is not very complicated and works for everything, which is a fair trade.