【问题标题】:Scala 3 extension overloading with different generic types具有不同泛型类型的 Scala 3 扩展重载
【发布时间】:2021-11-29 04:30:11
【问题描述】:

我正在从 Scala 2.13 迁移到 Scala 3,并且我正在尝试重写小型实用程序函数。在 2.13 中可以编写更通用的隐式和另一种更具体的,但在 Scala 3 中似乎不再可能。

  type Outcome[+E <: Fail, A] = Either[E, A]

  extension[A] (list: List[Outcome[ValidationFail, A]]) {
    def outcomeListAll: Outcome[ValidationFail, List[A]] = {
      val (left, right) = list.partitionOutcome
      if (left.isEmpty) {
        Right(right)
      } else {
        Left(left.reduce(_ + _))
      }
    }
  }

  extension[F <: Fail, A] (list: List[Outcome[F, A]])
    @deprecated
    def outcomeListAll: Outcome[Fail, List[A]] = {
      val (left, right) = partitionOutcome
      if (left.isEmpty) {
        Right(right)
      } else {
        Left(Fail.generic(left.map(_.getMessage).mkString(", "), left.head))
      }
    }
    def partitionOutcome: (List[F], List[A]) = {
      val left: List[F] = list.collect {
        case Left(l) => l
      }
      val right: List[A] = list.collect {
        case Right(r) => r
      }
      (left, right)
    }

当我尝试编译上面的代码 sn-p 时,我得到双重定义错误。至少根据this 文章应该解析为具有不同签名的方法。像这样:

<extension> def < (x: String)(y: String): Boolean = ...
<extension> def +: (xs: Seq[Elem])(x: Elem): Seq[Elem] = ...
<extension> infix def min(x: Number)(y: Number): Number = ...

我知道我可以简单地使用模式匹配,但我不能像使用方法那样重载扩展似乎很奇怪。

编译错误:

[error] -- [E120] Naming Error: /home/...testing/Main.scala:19:8 
[error] 19 |    def outcomeListAll: Outcome[Fail, List[A]] = {
[error]    |        ^
[error]    |Double definition:
[error]    |def outcomeListAll(list: scala.collection.immutable.List): scala.util.Either in object Main at line 7 and
[error]    |def outcomeListAll(list: scala.collection.immutable.List): scala.util.Either in object Main at line 19
[error]    |have the same type after erasure.
[error]    |
[error]    |Consider adding a @targetName annotation to one of the conflicting definitions
[error]    |for disambiguation.

【问题讨论】:

  • 我认为您应该能够使用@scala.annotation.targetName("someothername") 来避免双重定义错误。你到底在哪里得到错误,它说什么?
  • 我完全忽略了使用注释的编译器建议。谢谢。
  • 如果您可以发布问题的答案以显示代码更新,那就太好了;在这种情况下,包括注释。对于将来遇到相同问题的人来说,这将成为很好的文档。

标签: scala extension-methods implicit scala-3


【解决方案1】:

正如user所指出的,问题可以通过使用注解@targetName("...")来解决

  import scala.annotation.targetName

  type Outcome[+E <: Fail, A] = Either[E, A]

  extension[A] (list: List[Outcome[ValidationFail, A]]) {
    @targetName("outcomeListAllForValidationFail")
    def outcomeListAll: Outcome[ValidationFail, List[A]] = {
      val (left, right) = list.partitionOutcome
      if (left.isEmpty) {
        Right(right)
      } else {
        Left(left.reduce(_ + _))
      }
    }
  }

  extension[F <: Fail, A] (list: List[Outcome[F, A]])
    def outcomeListAll: Outcome[Fail, List[A]] = {
      val (left, right) = partitionOutcome
      if (left.isEmpty) {
        Right(right)
      } else {
        Left(Fail.generic(left.map(_.getMessage).mkString(", "), left.head))
      }
    }
    def partitionOutcome: (List[F], List[A]) = {
      val left: List[F] = list.collect {
        case Left(l) => l
      }
      val right: List[A] = list.collect {
        case Right(r) => r
      }
      (left, right)
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-09
    • 2020-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多