如何召唤`给定`成员?

问题描述 投票:0回答:1

假设我有一些类型类

trait FooBar[X]

FooBar[Int]
的实例:

given intIsFooBar: FooBar[Int] = new FooBar {}

现在,假设我有一个接口

Intf
有一些成员类型
A
并且还保证有一个
given FooBar[A]
:

trait Intf:
  type A
  given aIsFoobar: FooBar[A]

现在,我有类型

Int
,我有一个
FooBar[Int]
,但是我如何为
Int
实际实现这个接口?

如果我尝试

class IntImpl() extends Intf:
  type A = Int
  given aIsFoobar: FooBar[A] = summon

然后我得到“函数体IntImpl.aIsFoobar中的无限循环”错误,因为

summon
似乎看到
aIsFoobar
而不是
intIsFooBar
.

如果我尝试

summon
一些辅助辅助变量中的实例,就像这样:

class IntImpl() extends Intf:
  type A = Int
  private final val _aIsFoobar: FooBar[A] = summon
  given aIsFoobar: FooBar[A] = _aIsFoobar

然后我遇到了初始化顺序问题:

aIsFoobar
原来是
null
,我的应用程序崩溃了
NullPointerExceptions
,这有点荒谬。

我也尝试过

export
,但是这些都不起作用:

  export FooBar[Int] as aIsFoobar // doesn't compile, invalid syntax

我如何使“规范”

FooBar[Int]
作为
aIsFoobar
给定成员可用?


完整代码:

trait FooBar[X]

given intIsFooBar: FooBar[Int] = new FooBar {}

trait Intf:
  type A
  given aIsFoobar: FooBar[A]

object IntImpl extends Intf:
  type A = Int
  given aIsFoobar: FooBar[A] = summon
scala implicit scala-3 initialization-order given
1个回答
0
投票

在 Scala 2 中,您可以使用通过名称隐式隐藏的技巧

// Scala 2

trait FooBar[X] {
  def value: String
}
object FooBar {
  implicit val intIsFooBar: FooBar[Int] = new FooBar[Int] {
    override val value: String = "a"
  }
}

trait Intf {
  type A
  implicit def aIsFoobar: FooBar[A]
}

object IntImpl extends Intf {
  type A = Int

  override implicit val aIsFoobar: FooBar[A] = {
    lazy val aIsFoobar = ???
    implicitly[FooBar[A]]
  }
}

println(IntImpl.aIsFoobar.value) // a

在 Scala 3 中,使用擦除类型的模式匹配的规范方法是什么?

在 Scala 中是否有针对此格式参数的解决方法?

关于隐式解析的 NullPointerException

扩展具有需要隐式成员的特征的对象

在 Scala 3 中,这个技巧不起作用。

在 Scala 3 中,您可以尝试使方法 inline 并使用

scala.compiletime.summonInline
而不是
summon

// Scala 3

trait FooBar[X]:
  def value: String
object FooBar:
  given intIsFooBar: FooBar[Int] = new FooBar[Int]:
    override val value: String = "a"

trait Intf:
  type A
  /*inline*/ given aIsFoobar: FooBar[A]

object IntImpl extends Intf:
  type A = Int
  override inline given aIsFoobar: FooBar[A] = summonInline[FooBar[A]]

println(IntImpl.aIsFoobar.value) // a

覆盖内联方法:https://docs.scala-lang.org/scala3/reference/metaprogramming/inline.html#rules-for-overriding

请注意,通过内联我们修改了方法语义。隐式在调用站点解析,而不是在定义站点

// Scala 2

trait FooBar[X] {
  def value: String
}
object FooBar {
  implicit val intIsFooBar: FooBar[Int] = new FooBar[Int] {
    override val value: String = "a"
  }
}

trait Intf {
  type A
  implicit def aIsFoobar: FooBar[A]
}

object IntImpl extends Intf {
  type A = Int

  override implicit val aIsFoobar: FooBar[A] = {
    lazy val aIsFoobar = ???
    implicitly[FooBar[A]]
  }
}

{
  implicit val anotherIntFooBar: FooBar[Int] = new FooBar[Int] {
    override val value: String = "b"
  }

  println(IntImpl.aIsFoobar.value) // a
}
// Scala 3

trait FooBar[X]:
  def value: String
object FooBar:
  given intIsFooBar: FooBar[Int] = new FooBar[Int]:
    override val value: String = "a"

trait Intf:
  type A
  /*inline*/ given aIsFoobar: FooBar[A]

object IntImpl extends Intf:
  type A = Int
  override inline given aIsFoobar: FooBar[A] = summonInline[FooBar[A]]

{
  given anotherIntFooBar: FooBar[Int] = new FooBar[Int]:
    override val value: String = "b"

  println(IntImpl.aIsFoobar.value) // b
}

您可以询问如何在 Scala 3 中覆盖隐式而不更改定义站点语义。我不知道。

在 Scala 2 中,可以使用 Scala 2 宏实现内联

© www.soinside.com 2019 - 2024. All rights reserved.