我的问题是,在下面的代码片段中,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)
答案 0 :(得分:1)
最近,我有一个有趣的scala谜语涉及存在类型和类型别名(https://softwaremill.com/scala-riddle),我发现当类型别名不起作用时我们应该尝试使用有界抽象类型成员
我还没有想出任何模式可以告诉我在特定情况下我需要应用哪种类型的成员。 我无法在文档中找到答案,也许它是一个实现细节?
我希望有人能帮助我找到这样的模式或至少提供一些新的线索..
在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)
}
答案 1 :(得分:0)
我认为这是关于type
构造的推理错误(或可能是限制)。
编辑:错误消息是让我觉得它是一个错误的第一件事:
“类型不匹配;找到:需要Int(1):A”
如果将最后一行拆分为2,即
val t3 = TMap(1,2)
val t2: MapT2[Int] = t3
,然后它产生一个类似的pongy消息:
“类型不匹配;找到:Test1.this.TMap [Int,Int] required:Test1.this.MapT2 [Int](扩展为)Test1.this.TMap [A,A]”
鉴于A是'符号'而Int是一个类,它似乎在比较苹果和橙子。对不起,我不能再采取这种逻辑了!