Scala:对多态类型的单例实例不使用 Nothing

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

给定多态性特征,如

 trait Transform[T] { def apply( t: T ) : T }

人们可能想实现各种专门的实例,例如

 case class Add[Double] extends Transform[Double] { def apply( t: Double ) ... }
 case class Append[String] extends Transform[String] { def apply( t: String ) ... }

等等。现在经常需要的变换也是恒等变换。与其为每种类型 T 专门化标识,不如为所有类型 T 只使用一个单例实例。我的问题是:在 Scala 中实现这一目标的最佳方法是什么?

这是我到目前为止发现的:查看 List[T] 如何实现 List.empty[T] 和 Nil,我尝试使用 Nothing 作为类型 T。这似乎是有道理的,因为 Nothing 是所有其他类型的子类型:

 object Identity extends Transform[Nothing] {
    def apply( t: Nothing ) = t
 }

这似乎有效。但是,无论我在哪里想按原样使用此实例,就像这里一样:

 val array = Array[Transform[String]]( Transform.Identity )

我收到编译器错误“类型不匹配;发现:Identity.type,必需:Transform[String]”。为了使用它,我必须显式地转换它:

 ... Identity.asInstanceOf[Transform[String]]

我不确定这是最好的,甚至是“正确”的方法。感谢您的任何建议。

scala polymorphism singleton
2个回答
5
投票

正如@Kim Stebel指出的那样,你的

Transform[T]
T
中是不变的(并且必须是因为
T
同时出现在
def apply(t : T) : T)
中的同变体和逆变体位置,所以
Transform[Nothing]
不是
的子类型) Transform[String]
并且无法做到。

如果您主要关心的是 Kim 的

def Id[A]
每次调用时的实例创建,那么您最好的模型是 Predef 中
conforms
的定义,

private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]

即。使用多态方法,返回一个转换为适当类型的单例值。这是删除就是胜利的场合之一。

适用于您的情况,我们会,

object SingletonId extends Transform[Any] { def apply(t : Any) = t }
def Id[A] = SingletonId.asInstanceOf[Transform[A]]

示例 REPL 会话,

scala> Id("foo")
res0: java.lang.String = foo

scala> Id(23)
res1: Int = 23

4
投票

由于

T
中的类型参数
Transform[T]
是不变的,
Transform[Nothing]
不是
Transform[String]
的子类型,因此编译器会抱怨它。但在这里使用
Nothing
无论如何都没有意义,因为永远不可能有
Nothing
的实例。那么如何将一个传递给
apply
方法呢?你需要再次施放。我能看到的唯一选项是:

scala> def Id[A] = new Transform[A] { override def apply(t:A) = t }
Id: [A]=> java.lang.Object with Transform[A]

scala> Id(4)
res0: Int = 4

scala> Id("")
res1: java.lang.String = ""
© www.soinside.com 2019 - 2024. All rights reserved.