在 GitHub 上編輯此頁面

依名稱上下文參數

可以宣告依名稱內容參數,以避免發散的推論擴充。範例

trait Codec[T]:
  def write(x: T): Unit

given intCodec: Codec[Int] = ???

given optionCodec[T](using ev: => Codec[T]): Codec[Option[T]] with
  def write(xo: Option[T]) = xo match
    case Some(x) => ev.write(x)
    case None =>

val s = summon[Codec[Option[Int]]]

s.write(Some(33))
s.write(None)

與一般依名稱參數的情況相同,內容參數 ev 的引數會依需求評估。在上述範例中,如果選項值 xNone,則完全不會評估。

如果需要防止發散的擴充,內容參數的合成引數會由區域 val 支援。

合成依名稱內容參數(類型為 => T)引數的精確步驟如下。

  1. 建立類型為 T 的新 given

    given lv: T = ???
    

    其中 lv 是任意的新名稱。

  2. 此 given 並未立即可用作引數推論的候選項(使其立即可用會導致合成運算中出現迴圈)。但它會在所有再次尋找依名稱內容參數引數的巢狀內容中可用。

  3. 如果此搜尋使用表達式 E 成功,且 E 包含對 lv 的參照,請將 E 替換為

    { given lv: T = E; lv }
    

    否則,不變更傳回 E

在上述範例中,s 的定義會擴充為如下。

val s = summon[Test.Codec[Option[Int]]](
  using optionCodec[Int](using intCodec)
)

未產生任何區域提供實例,因為合成引數並非遞迴。

參考

如需更多資訊,請參閱 Issue #1998 和相關的 Scala SIP

本文內容