arrays - Scala:如何指定暗示相等的类型参数边界?

标签 arrays scala types parameters type-bounds

不要被长文本吓倒,这些要点非常琐碎,但需要一些代码来说明问题。 :-)

设置:

假设我想创建一个特征,这里建模为某种Converter,它本身是通用的,但有一个类型化方法convert(),它返回一个适当类型的结果对象,例如 Container[T]:

 trait Converter {
   def convert[T]( input: T ) : Container[T]
 } 
 trait Container[T]  // details don't matter

我的问题是关于方法的类型约束,特别是强制相等性,并且有两个密切相关的部分。

第 1 部分:现在假设有一种专门的容器类型,特别适合基于数组的内容,如下所示:

 object Container {
   trait ForArrays[U] extends Container[Array[U]] 
 }

考虑到这种可能性,我现在想将转换器,特别是 convert() 方法的返回类型专门化为专门的 Container.ForArrays 类型:

 object Converter {
   trait ForArrays extends Converter {
     // the following line is rubbish - how to do this right?
     def convert[E,T <: Array[E]]( input: T ) : Container.ForArrays[E]
   } 
 }

这样我就可以做这样的事情:

val converter = new Converter.ForArrays { ... }
val input = Array( 'A', 'B', 'C' )   
val converted : Container.ForArrays[Char] = converter.convert( input )

基本上,如果已知转换器的类型为 Converter.ForArrays,我希望 Scala 也能将 convert[Char]() 的专门返回类型推断为Container.ForArrays[Char],即匹配的容器类型加上输入的数组类型。这或类似的事情可能吗?如果可以,我该怎么做?例如。如何指定 Convert() 上的类型参数/界限(提供的只是一个替代 - 我不知道如何执行此操作)。哦,当然,这样它仍然重写它的 super 方法,否则什么也得不到。

第 2 部分:作为后备方案,如果这不可能,我当然可以将转换函数插入以数组为中心的变体中,如下所示:

 trait Converter   // now pretty useless as a shared trait
 object Converter {
   trait ForValues extends Converter { 
     def convert[T]( input: T ) : Container[T] 
   }
   trait ForArrays extends Converter {
     def convert[E]( input: Array[E] ) : Container.ForArrays[E]
   } 
 }

好的。现在假设我有一个更专业的 Converter.ForArrays.SetBased ,它可以在内部使用一组 E 类型的元素(与“输入”数组元素类型相同)在转换。然而,该集合现在是特征的参数,如下所示:

 case class SetBased( set: Set[F] ) extends Converter.ForArrays {
   // the following line is also rubbish...
   def convert[E = F]( input: Array[E] ) : Container.ForArrays[E] = {...}
 }

这又是关于convert()方法的类型参数。这里的困难是:如何将类的类型参数 - F - 粘合到方法的类型参数 - E - 这样 Scala 编译器只会让用户使用其元素与集合元素匹配的数组调用 convert()?示例:

val set = Set( 'X', 'Y', 'Z' )
val converter = new Converter.ForArrays.SetBased( set )
val input = Array( 'A', 'B', 'C' )   
val converted : Container.ForArrays[Char] = converter.convert( input )

最佳答案

不,你不能。出于同样的原因,您在重写方法时不能缩小参数类型或扩大返回类型(但可以缩小返回类型)。不过,您可以执行以下操作(对于您的后备解决方案):

trait Converter {
  type Constraint[T]
} 

trait ForArrays extends Converter {
  def convert[E]( input: Array[E] )( implicit ev : Constraint[T] ) : Container.ForArrays[E]
}

case class SetBased[F](set: Set[F]) extends Converter {
   type Constraint[T] = T =:= F
   def convert[E]( input: Array[E] )( implicit ev : E =:= F ) = ...
} 

关于arrays - Scala:如何指定暗示相等的类型参数边界?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7886551/

相关文章:

scala - Play Framework : EhCache issue on every code hot compile

scala - 如何在 spark-scala 中将 Iterable[String] 保存到 hdfs

generics - 是否可以在when语句中返回与类型参数相同的类型

java - 将 Vector2 乘以标量 (LibGDX)

javascript - 我们可以在js中同时映射两个数组吗?

c++ - 数组声明之间的区别

javascript - Scala + Play + Akka。是否需要 Backbone.js?

go - 如何使用 Go 反射 pkg 获取 slice 结构字段的类型?

javascript - 分割字符串会导致无限循环

arrays - 将Struct数组元素作为参数传递给Go语言中的函数