具有额外约束的 Scala 无形 KList

标签 scala path-dependent-type shapeless klist

我想采用这种模式:

 def accept[T](a: RList[T]) = true
 def accept[T, V](a: RList[T], b: RList[V])(implicit ev: a.S =:= b.S) = true
 def accept[T, V, Q](a: RList[T], b: RList[V], c: RList[Q])(implicit ev: a.S =:= b.S, ev2: b.S =:= c.S) = true

但让它接受KList,而不是手动覆盖所有参数。基本上我想说的是,“取任意数量的 RList,它们具有相同的 S 成员类型”

RList 是一个特征,包含一个类型 S。 (有关 RList 的更多背景知识以及我这样做的原因,请参阅:Constrain function based on origin (Path Dependent type? Type Generation?))

最佳答案

看起来你正在做的只是试图让编译器检查类型是否一致,因为你的方法总是返回 true。

您是否可以接受一个“RLists 列表”,而不是制作接受任意数量的这些方法,而保证 S 全部匹配?

下面是这样一个列表的构建方式:

package rl {

// A simplified version of your RList:
trait RList[T] {
  type S
  def data: List[T]
}

// A list of RLists which have identical S
sealed trait RListList 

// RListNil is an empty list
trait RListNil extends RListList {
  def ::[H <: RList[_]](h: H) = rl.::[h.S,H,RListNil](h, this)
}
// there is exactly one RListNil
case object RListNil extends RListNil

// List can be a cons cell of lists sharing the same S
final case class ::[S, H <: RList[_], T <: RListList](head: H, tail: T) extends RListList {

  // We only allow you to cons another to this if we can find evidence that the S matches
  def ::[H2 <: RList[_]](h: H2)(implicit ev: =:=[h.S,S]) = rl.::[S,H2,::[S,H,T]](h, this)
}

现在,如果我们试图构造一个没有所有 S 类型都一致的 RListList,编译器会抓到我们:

object RListTest {

  val list1 = new RList[Int] { type S = String; def data = List(1,2,3,4) }
  val list2 = new RList[String] { type S = String; def data = List("1","2","3","4") }
  val list3 = new RList[Double] { type S = Float; def data = List(1.1,2.2,3.3,4.4) }

  val listOfLists1 = list1 :: RListNil // fine
  val listOfLists2 = list2 :: listOfLists1 // still fine, since list1 and list2 have the same S
  val listOfLists3 = list3 :: listOfLists2 // compiler error: Cannot prove that java.lang.String =:= Float

}

这是使用依赖方法类型,这意味着您需要使用 scala 2.10 或需要在 2.9.x 中使用 -Ydependent-method-types 开关进行编译

关于具有额外约束的 Scala 无形 KList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12046974/

相关文章:

scala - sparkSession.sparkContext对于本地Spark集群为null

scala - Akka 经典与 Akka 打字

scalaz.Equal 用于路径依赖类型

scala - 如何在编译时使用 shapeless 将 case 类字段的名称作为字符串/符号获取?

scala - 带有仿函数的数值映射

scala - 令人困惑的 Scala 高阶函数调用语法

scala - Map到TreeMap的深度转换

scala - Scala 的路径依赖类型是什么意思?

scala - 禁止生成申请案例类

scala - 折叠具有未知类型的 HList