Это продолжение одного из моих предыдущих вопросов:
В scala бесформенный, возможно ли использовать литеральный тип в качестве универсального c параметра типа?
Я пытаюсь написать scala код для умножения вектора, используя бесформенную форму, чтобы компилятор знал размерность каждого вектора:
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 = {}
}
В идеале неявное fromInt
может вывести v.narrow
(Witness может работать только с финальным одноэлементным типом), но он не ведет себя так:
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
}
Последние 2 строки не вызывают ошибку компиляции, что противоречит моему гипотеза. Есть ли способ изменить это поведение так, чтобы KN, созданный с помощью fromInt
, мог найти правильный тип? Я использую scala -2.12, поэтому единственный тип бесформенного типа, кажется, единственный вариант.