Scala 3 多态扩展方法不适用于文字类型

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

在我的项目中,我使用 Scala 3,我认为我发现了一个奇怪的情况,即多态扩展方法不能很好地处理自定义文字类型。我减少了代码,以便我可以用最少的代码来显示问题:

object Demo2:
  extension [T](either: Either[String, T])
    def toOptionCustom: Option[T] = either.fold(_ => None, Some(_))

  type MyValue = "value1" | "value2" | "value3"
  val myValues: List[MyValue] = List("value1", "value2", "value3")
  def toMyValue(value: String): Either[String, MyValue] = myValues.find(_.toString == value).toRight("Invalid value")
  def hello(myValue: MyValue): String = s"Hello $myValue"

  def demo1: Option[String] =
    toMyValue("value1").toOption.map(hello) // this line compiles
  
  def demo2: Option[String] =
    toMyValue("value1").fold(_ => None, Some(_)).map(hello) // this line also compiles
  
  def demo3: Option[String] =
    toMyValue("value1").toOptionCustom.map(hello) // but this line doesn't compile

编译器无法编译最后一行,指出函数

hello
应该是
String => String
类型,在我看来这是错误的。它应该接受
MyValue => String
类型函数并且
hello
符合它。
toOptionCustom
方法基本上是我对
toOption
的自定义实现,我认为它应该有效。
demo2
demo3
基本相同,只是
demo3
经过了扩展方法。我是不是错过了什么?

我的Scala版本是3.4.2,这是目前最新的。

scala extension-methods scala-3
1个回答
0
投票

问题与您的

Singleton
类型的
MyValue
性质有关。如果您将
<: Singleton
添加到扩展类型参数中,它就可以正常工作:

extension [T <: Singleton](either: Either[String, T])

Scala 中的类型推断将单例类型扩展到底层的非单例类型。在您的示例中,

MyValue
的底层非单例类型确实是
String

以下示例展示了这种特殊性:

def foo[T](opt: Option[T]) = opt
def bar[T <: Singleton](opt: Option[T]) = opt

val one: Option[1] = Some(1)

val a = foo(one)  // (a: Option[Int])
val b = bar(one)  // (b: Option[1])

另请参阅 SingletonSIP-23

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