簡體   English   中英

Scala 在通用特征方法中找不到案例 class 參數

[英]Scala can't find case class parameter in generic trait method

我有以下案例 class 使用通用方法實現特征。 目標是讓每個擴展特征的 class S以該方法使用S S的值的方式實現該方法。

case class Foo(x: Int) extends Bar {
  def baz[Foo](v: Foo): Foo = {
    Foo(v.x + x)
  }
}

trait Bar {
  def baz[S <: Bar](v: S): S
}

但是,在編譯時,我收到以下錯誤,即找不到x

error: value x is not a member of type parameter Foo
    Foo(v.x + x)
          ^
one error found

對我來說更奇怪的是,當我將方法更改為返回Foo(3) (從而刪除對x的訪問)時,我收到以下錯誤:

error: type mismatch;
 found   : <empty>.Foo
 required: Foo(in method baz)
    Foo(3)
       ^
one error found

我不確定<empty>.FooFoo(in method baz)類型是什么,以及為什么這兩個不僅僅是Foo 顯然,我對 Scala 的類型系統有一些誤解,因此不勝感激。

編輯

我希望有多個類實現Bar 我希望能夠在Bar類型的 val 上調用baz

在下面的示例中考慮ab是從其他地方獲得的,根據我的程序的邏輯,我知道它們都是相同 class 的實例(不一定是Foo )。 在這種情況下,有什么辦法可以合法地打電話給baz嗎? 我知道我可以將兩者都轉換為Foo ,但這發生在我不知道具體的 class 是什么的情況下。 也就是說,我知道ab的類型都是T <: Bar相同的T ,但我不知道T是什么。

object Foo {
  def main(args: Array[String]): Unit = {
    val a: Bar[_] = Foo(3)
    val b: Bar[_] = Foo(2)
    a.baz(b) // This call is invalid
  }
}

baz的類型參數不像你想象的那樣工作。 在原始特征Bar中,它告訴您可以傳入任何擴展BarbazS將 output 另一個S 這意味着在Foo中,您不僅要處理Foo還要處理從Bar繼承的其他類。

此外,類型參數Foo會影響 class Foo 它等價於:

case class Foo(x: Int) extends Bar {
  def baz[T](v: T): T = {
    Foo(v.x + 1)
  }
}

TFooBar完全無關,因此您的方法也不滿足baz的簽名,因為它實際上應該是T <: Bar

我認為你想要做的是通過給Bar本身的類型參數S (這稱為 F 有界多態性):

case class Foo(x: Int) extends Bar[Foo] {
  def baz(v: Foo): Foo = {
    Foo(v.x + 1)
  }
}

trait Bar[S <: Bar[S]] { this: S =>
  def baz(v: S): S
}

這里的S基本上可以用來指代 class 擴展Bar的類型,因此編譯器知道baz輸入和輸出Foo s。

您以后可以像這樣使用它:

def test[T <: Bar[T]](a: T, b: T) = a.baz(b)

但是,根據您的編輯,您似乎想要一個類型類。 我建議將Bar的定義更改為以下內容:

trait Bar[T] {
  def baz(t: T): T
}

然后Foo可以這樣定義:

case class Foo(x: Int)

FooBar的隱式實例將單獨提供(可能在Bar的伴隨對象中):

object Bar {
  implicit val fooBar: Bar[Foo] = new Bar {
    def baz(v: Foo): Foo = Foo(v.x + 1)
  }
  //For convenience
  def apply[T](implicit bar: Bar[T]): bar
}

您以后可以像這樣使用它:

def test[T : Bar](a: T, b: T) = Baz[T].bar(a, b)

有關返回電流類型問題的更多信息,請參閱 F-bounded polymorphism over typeclass 的優勢

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM