3

私はこのパターンを取りたい:

 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メンバータイプのsをいくつでも取得する」と言いたいです。

RListタイプを含む特性Sです。(RListの背景と、これを行う理由については、「起点に基づく関数の制約(パス依存型?型生成?)」を参照してください) 。

4

1 に答える 1

2

メソッドは常にtrueを返すため、実行しているのは、型が一致することをコンパイラーにチェックさせようとしているように見えます。

おそらく、これらの任意の数を受け入れるメソッドを作成する代わりに、Sがすべて一致することが保証されている「RListのリスト」を受け入れることができますか?

このようなリストの作成方法は次のとおりです。

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スイッチを使用してコンパイルする必要があります。

于 2012-08-21T06:09:53.767 に答える