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

Gre*_*idt 2 polymorphism singleton scala nothing

给出了像多态的特征

 trait Transform[T] { def apply( t: T ) : T }
Run Code Online (Sandbox Code Playgroud)

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

 case class Add[Double] extends Transform[Double] { def apply( t: Double ) ... }
 case class Append[String] extends Transform[String] { def apply( t: String ) ... }
Run Code Online (Sandbox Code Playgroud)

现在,经常需要的变换也是身份变换.对于所有类型T,最好只使用一个单例实例,而不是为每个类型T专门设置标识.我的问题是:在Scala中实现此目的的最佳方法是什么?

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

 object Identity extends Transform[Nothing] {
    def apply( t: Nothing ) = t
 }
Run Code Online (Sandbox Code Playgroud)

这似乎有效.但是,无论我在哪里,都希望按原样使用此实例,如下所示:

 val array = Array[Transform[String]]( Transform.Identity )
Run Code Online (Sandbox Code Playgroud)

我得到编译器错误"类型不匹配;找到:Identity.type,required:Transform [String]".为了使用它,我必须明确地使用它:

 ... Identity.asInstanceOf[Transform[String]]
Run Code Online (Sandbox Code Playgroud)

我不确定这是最好还是"正确"的做法.谢谢你的建议.

Mil*_*bin 5

正如@Kim Stebel所指出的那样你Transform[T]是不变的T(并且必须因为T在共同和反变体位置都发生,def apply(t : T) : T)所以Transform[Nothing]不是一个子类型,Transform[String]也不能成为.

如果您主要关注的是每次调用Kim的实例,def Id[A]那么您最好的模型是conformsPredef中in 的定义,

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

即.使用多态方法,将单个值转换为适当的类型.这是擦除胜利的场合之一.

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

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

示例REPL会话,

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

scala> Id(23)
res1: Int = 23
Run Code Online (Sandbox Code Playgroud)