问题
This is a follow-up of one of my previous questions:
In scala shapeless, is it possible to use literal type as a generic type parameter?
I'm trying to write scala code for vector multiplication, while using shapeless to make the compiler aware of the dimension of each vector:
trait IntTypeMagnet[W <: Witness.Lt[Int]] extends Serializable {
def witness: W
}
object IntTypeMagnet {
case class Impl[W <: Witness.Lt[Int]](witness: W) extends IntTypeMagnet[W] {}
implicit def fromInt[W <: Int](v: W): Impl[Lt[W]] = Impl(Witness(v))
implicit def fromWitness[W <: Witness.Lt[Int]](witness: W): Impl[W] = Impl(witness)
}
trait Axis extends Serializable
case object UnknownAxis extends Axis
trait KnownAxis[W <: Witness.Lt[Int]] extends Axis {
def n: Int
def ++(that: KnownAxis[W]): Unit = {}
}
Ideally the implicit fromInt
can deduce v.narrow
(Witness can only work on final, singleton type), yet it doesn't behave as so:
object Attempt1 {
case class KN[W <: Witness.Lt[Int]](magnet: IntTypeMagnet[W]) extends KnownAxis[W] {
val n = magnet.witness.value
}
// looking good, works as intended
KN(1) ++ KN(1)
KN(Witness(1)) ++ KN(2)
KN(Witness(1)) ++ KN(Witness(2))
val v1_simple: KN[Lt[Int]] = KN(1)
KN(1) ++ KN(2) // should break
KN(1) ++ KN(Witness(2)) // should break
}
The last 2 lines doesn't cause any compilation error, which contradicts my hypothesis. Is there a way to change this behaviour such that KN created using fromInt
can find the correct type? I'm using scala-2.12 so the singleton type of shapeless seems to be the only option.
来源:https://stackoverflow.com/questions/60592107/when-using-the-singleton-type-feature-of-scala-shapeless-how-to-force-the-compi