gpt4 book ai didi

Scala:使用隐式证据的通用方法无法编译

转载 作者:行者123 更新时间:2023-12-02 21:16:10 26 4
gpt4 key购买 nike

我正在通过《Scala for the Impressive》一书中的练习来学习 Scala。问一个问题:

Given a mutable Pair[S, T] class, use a type constraint to define a swap method that can be called if the type parameters are the same.

我的代码:

class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S) {
val temp = first
first = second // doesn't compile
second = temp
}
}

上面的代码无法编译,并提示 firstsecond 是不同的类型。好吧,我只是很好地告诉编译器它们不是。我怎样才能让它闭嘴?

最佳答案

您刚刚告诉编译器传递给您的类的类型为 TS应该相等 - 你只需要它们相等的证据,这可以用来推断实际的 TS当您传递实际类型时正确(但不在泛型类本身内部)。这并不意味着TS是可以互换的。顺便说一句,它不会改变任何东西,但你通过定义新的 S 犯了一个错误。和T ,应该是:

  class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S) { //without [S, T] - they are unrelated to original ones, it's whole new names
val temp = first
first = second // doesn't compile
second = temp
}
}

但是它仍然无法编译。为什么?想想看:

 def getBoth(implicit ev: T =:= S) = List(first, second)

那么编译器应该推断什么返回类型? List[T]List[S] 。它唯一能做的就是List[Any] 。因此同时拥有相同和不同的类型是没有意义的。如果您想要不同的名称 - 只需使用 type S = T不需要任何证据。

拥有 S 的真实情况是什么?和T构造函数不同,某些方法相同。这在逻辑上根本就是不正确的(当谈论抽象类型时 - 而不是具体的替换)。

顺便说一句,=:=不是编译器功能 - 编译器中没有对此进行特殊处理。整个实现是在 scala Predef 内部:

@implicitNotFound(msg = "Cannot prove that ${From} =:= ${To}.")
sealed abstract class =:=[From, To] extends (From => To) with Serializable
private[this] final val singleton_=:= = new =:=[Any,Any] { def apply(x: Any): Any = x }
object =:= {
implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A]
}

所以它只是 tpEquals[A]隐式采用 A 类型并给你A =:= A - 当您需要T =:= U时它试图进行这样的转换,而这种转换仅适用于相同的类型。检查隐式本身的过程实际上仅在您传递实际 T 时才会发生。和U ,而不是在您定义它们时。

关于您的具体问题:

class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S) {
val temp = first
first = second.asInstanceOf[T]
second = temp.asInstanceOf[S]
}
}

scala> new Pair(5,6)
res9: Pair[Int,Int] = Pair@6bfc12c4

scala> res9.swap

scala> res9.first
res11: Int = 6

或者只是(正如@m-z和@Imm建议的那样):

class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S, ev2: S =:= T) {
val temp = first
first = second
second = temp
}
}

T =:= S延伸T => S并且这个隐式添加的函数(即使作为对象)被解释为从 T 的隐式转换至S在 Scala 中,所以它的工作方式就像两种类型是相等的,这非常酷。

关于Scala:使用隐式证据的通用方法无法编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30699996/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com