При использовании функции одноэлементного типа Scala без формы, как заставить компилятор использовать узкий / одноэлементный тип в качестве неявного параметра? - PullRequest
1 голос
/ 09 марта 2020

Это продолжение одного из моих предыдущих вопросов:

В 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, поэтому единственный тип бесформенного типа, кажется, единственный вариант.

...