When using the singleton type feature of Scala shapeless, how to force the compiler to use narrow/singleton type as an implicit parameter?

余生颓废 提交于 2020-05-14 07:21:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!