Scala бесформенный 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 и почему я делаю это, см.: Ограничить функцию, основанную на происхождении (тип, зависящий от пути? Генерация типа?))
1 ответ
Похоже, что вы просто пытаетесь заставить компилятор проверить соответствие типов, поскольку ваши методы ВСЕГДА возвращают true.
Может быть, вы, возможно, вместо создания методов, которые принимают произвольное число из них, принимают "Список списков R", который гарантированно будет иметь все 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)
}
Теперь, если мы попытаемся создать RListList, в котором не совпадают все типы S, компилятор поймает нас:
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 или вам нужно скомпилировать с ключом -Ydependent-method-types в 2.9.x