scala - 防止 Scala 特征成为 SAM 类型

标签 scala implicit single-abstract-method

我有一个trait Modifier[-A] extends (A => Unit)

但是,Scala 2.12 magic SAM 语法会默默地将任何 lambda 文字(如 el => foo)转换为 Modifier,因为 Modifier 符合 SAM 类型(此语法的适用规则为 here)。

我不希望这种转换应用于我的修饰符特征,因为它会干扰我的库的语法。简而言之,我有一个从 A => Modifier[A]Modifier[A] 的隐式转换。在 2.12 中,lambda 文字(例如 thisNode => someModifier(thisNode, otherParam))不会触发该转换,因为 Scala 将 A => Modifier[A] lambda 魔法化为一个 Modifier[A] 本身,但不是正确的。

我知道有几种方法可以解决这个问题:

1) Modifier trait 不应扩展 Function1,而应定义其自己的抽象 def apply[X](element: El): Unit 方法。由于幻像类型参数 X,未应用 SAM 语法。

2) 添加一个无意义的抽象 protected[this] def foo 到 Modifier trait。这将使 SAM 语法不适用,如果我正确理解 Scala.js 死代码消除,这个伪造的方法将从运行时消除。

我倾向于选项 1,因为它似乎减轻了 Modifier 实现者的负担,而且更明显的是它不会影响运行时性能。

但它仍然看起来很老套,而且我不喜欢无用的 phantom 类型会泄漏到我的库的 API 中。有没有更好的办法?

感谢您的任何建议。

最佳答案

从 Scala 2.12 的文档中可以看出 Sam Conversions precedes implicits :文档还讨论了覆盖此行为的潜在解决方案。

如果您需要自动进行转换,两种方法都是合理的:

  1. 如果您扩展自己的自定义 MyFunction1,您可能会失去标准库的组合优势

  2. 如果您添加一个无意义的方法,一旦您使用定义在 Function1

    上的方法执行组合操作,您将回退到标准 Function1

在您的情况下,我想这两种方法都可以,因为您的 Modifier apply 正在返回 Unit 并且您不会将这些操作通过管道或连接在一起。

关于scala - 防止 Scala 特征成为 SAM 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48971622/

相关文章:

scala - 无法证明 Unit < :< (T, U)

scala - scala.Unit 与 () 不同吗?

scala - 我如何在 Scala 中拆分充满选项的案例类

scala - Spark : How to map an RDD when access to another RDD is required

scala - Dotty中给出的如何使用?

generics - Scala 泛型和数字隐式

Scala 隐式转换未在合适的目标上执行

scala - SAM 和匿名函数的区别