在scala shapeless中,可以使用文字类型作为泛型类型参数吗?

问题描述 投票:4回答:1

假设我正在编写矢量乘法程序。遵循本文中的要求:

https://etrain.github.io/2015/05/28/type-safe-linear-algebra-in-scala

仅当两个向量的维数相等时,乘法才能成功编译。为此,我定义了一个通用类型Axis,该类型使用无形文字类型(维数)作为类型参数:

import shapeless.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 = {}
}

object KnownAxis {

  val w1 = Witness(1)
  val w2 = Witness(2)

  case class K1(n: Witness.`1`.T) extends KnownAxis[w1.type]
  case class K2(n: Witness.`2`.T) extends KnownAxis[w2.type]

//  K2(2) ++ K1(1) // doesn't compile

  K2(2) ++ K2(2)
}

到目前为止,到目前为止,当我尝试对所有n进行归纳时,都会出现问题:

  case class KN[W <: Witness.Lt[Int]](n: W#T) extends KnownAxis[W]

  KN(1)

以上代码触发编译错误:

Axis.scala:36: type mismatch;
 found   : Int(1)
 required: this.T
[ERROR]   KN(1)
[ERROR]      ^
[ERROR] one error found

我的问题是:为什么Spark无法专注于更精细的类型Witness. 1 .T,而是使用类型Int?要重写此行为需要做什么,以便可以成功定义案例类KN

scala shapeless dependent-type
1个回答
0
投票

我期望的工作方式(不确定为什么不这样做)是指定类型参数:

KN[Witness.`1`](1)
// error: type arguments [scala.this.Any] do not conform to method apply's type parameter bounds [W <: shapeless.this.Witness.Lt[scala.this.Int]]

有效的方法:

case class KN[W <: Witness.Lt[Int]](w: W) extends KnownAxis[W] {
  val n = w.value
}

KN(Witness(1))

它似乎适合您问题的要求,但我不知道它是否可以与您的其余代码一起使用。

您可能还想考虑这种在Scala 2.13中不需要Shapeless的替代方法:

trait Axis extends Serializable

case object UnknownAxis extends Axis

trait KnownAxis[W <: Int with Singleton] extends Axis {

  def n: W

  def ++(that: KnownAxis[W]): Unit = {}
}

case class KN[W <: Int with Singleton](n: W) extends KnownAxis[W]

KN(1)

对于2.12

import shapeless.syntax.singleton._

...
KN(1.narrow)
© www.soinside.com 2019 - 2024. All rights reserved.