6

私の質問は、次のスニペットで、c2 はコンパイルに合格できますが、t2 は失敗するということです。なぜ?

  type PairT[A, B] = { //structural type
    type T1 = A
    type T2 = B
  }
  class PairC[A, B] {
    type T1 = A
    type T2 = B
  }
case class TMap[A, B](a: A, b: B)
type MapC2[A] = TMap[p.T1, p.T2] forSome { val p: PairC[A, A] }
type MapT2[A] = TMap[p.T1, p.T2] forSome { val p: PairT[A, A] }
  val c2: MapC2[Int] = TMap(1,2)
  val t2: MapT2[Int] = TMap(1,2)
4

2 に答える 2

1

最近、存在型と型エイリアス ( https://softwaremill.com/scala-riddle )を含む興味深い scala なぞなぞがあり、型エイリアスが機能しない場合は、制限付きの抽象型メンバーを試す必要があることがわかりました。

特定の状況でどの種類のメンバーを適用する必要があるかを教えてくれるパターンがわかりません。ドキュメントで答えが見つかりません。実装の詳細でしょうか?

そのようなパターンを見つけるのを手伝ってくれる人、または少なくともいくつかの新しい手がかりを教えてくれる人がいることを願っています..

コードを機能させる方法

内部では、PairT型エイリアス ( type T1 = A) を厳密に境界付けられた抽象型 ( type T1 >: A <: A) に置き換えました。.. 動作します (scalac 2.11.4)。

さらに興味深いのPairCは、具体的なクラスである は、型エイリアスでのみ機能します。それらを制限付き抽象型メンバーに置き換えようとすると、コンパイル エラーが発生します。

以下は、私の変更後のコード全体です。

package so1

import scala.language.existentials

object SOPuzzle {

  type PairT[F, S] = {
    type T1 >: F <: F
    type T2 >: S <: S
  }

  class PairC[F, S] {
    type T1 = F
    type T2 = S
  }

  case class TMap[T, U](a: T, b: U) {
    def consumeA(a: T): T = a
    def consumeB(b: U): U = b
  }

  type MapC2[A] = TMap[p.T1, p.T2] forSome {val p: PairC[A, A]}

  type MapC2V2[A] = TMap[PairC[A, A]#T1, PairC[A,A]#T2]

  type MapT2[A] = TMap[p.T1, p.T2] forSome {val p: PairT[A, A]}

  type MapT2V2[A] = TMap[PairT[A, A]#T1, PairT[A, A]#T2]

  val c2: MapC2[Int] = TMap(1, 2)
  val c2v2: MapC2V2[Int] = TMap(1, 2)
  val t2: MapT2[Int] = TMap(1, 2)
  val t2v2: MapT2V2[Int] = TMap(1, 2)

  val i1:Int = c2.consumeA(0)
  val i2:Int = c2.consumeB(0)

  val i3:Int = c2v2.consumeA(0)
  val i4:Int = c2v2.consumeB(0)

  val i5:Int = t2.consumeA(0)
  val i6:Int = t2.consumeB(0)

  val i7:Int = t2v2.consumeA(0)
  val i8:Int = t2v2.consumeB(0)
}
于 2015-01-17T14:15:22.603 に答える
0

typeコンストラクトに関する推論バグ(またはおそらく制限)だと思います。

編集:エラーメッセージは、それがバグだと最初に思ったものでした:

「型が一致しません。見つかりました: Int(1) が必要です: A」

最後の行を 2 つに分割すると、つまり

val t3 = TMap(1,2)
val t2: MapT2[Int] = t3

の場合、同様の pongy メッセージが生成されます。

「タイプの不一致; 検出: Test1.this.TMap[Int,Int] 必須: Test1.this.MapT2[Int] (展開先) Test1.this.TMap[A,A]"

A が「シンボル」で、Int がクラスであることを考えると、リンゴとオレンジを比較しているように見えます。申し訳ありませんが、このロジックをこれ以上進めることはできません!

于 2013-07-15T09:10:18.013 に答える