我想创建一个数组(或列表,arraybuffer等),该数组只能包含具有定义隐式排序的类实例(例如,int,长,double)。
类似的东西:
val ab = new ArrayBuffer[???]()
ab += 7
ab += 8.9
ab += 8L
我不想将这些值彼此比较。
只需使用类型类约束,如下所示
def createList[T: Ordering](values: T*) = values.toList
T: Ordering
仅意味着仅允许在范围中以 Ordering
实例作为参数传递给函数的类型。
scala> def createList[T: Ordering](values: T*) = values.toList
createList: [T](values: T*)(implicit evidence$1: Ordering[T])List[T]
scala> case class Cat()
defined class Cat
scala> createList(1, 2, 3)
res2: List[Int] = List(1, 2, 3)
scala> createList(Cat())
<console>:15: error: No implicit Ordering defined for Cat.
createList(Cat())
^
整数订购在范围中可用,但cat订购在范围中不可用。因此,在提供Ordering[Cat]
Cat
值现在让我们提供一些伪造的订单,看看编译器是否接受Cat
作为参数
scala> implicit val orderingCat: Ordering[Cat] = (a: Cat, b: Cat) => ???
orderingCat: Ordering[Cat] = $anonfun$1@6be766d1
scala> createList(Cat())
res4: List[Cat] = List(Cat())
它有效。
如果您真的想拥有不同类型的对象列表,并且仍然能够在编译时静态检查有关该列表中这些对象的内容,则必须使用诸如HList
来自无形。这是一个示例,说明了您如何有两个异质列表,并且在编译时间仍检查两个列表的每个 element evertains everna。
import shapeless._
import shapeless.ops.hlist.{LiftAll, Zip, Mapper}
object lt extends Poly1 {
implicit def instance[A] = at[(Ordering[A], A, A)] {
case (ord, a, b) => ord.lt(a, b)
}
}
def areLessThan[L <: HList, O <: HList, OLL <: HList](a: L, b: L)(
implicit
ord: LiftAll.Aux[Ordering, L, O],
zip: Zip.Aux[O :: L :: L :: HNil, OLL],
map: Mapper[lt.type, OLL]
) = zip(ord.instances :: a :: b :: HNil).map(lt)
使用它:
scala> val a = 1 :: "b" :: Option(4L) :: HNil
a: Int :: String :: Option[Long] :: shapeless.HNil = 1 :: b :: Some(4) :: HNil
scala> val b = 2 :: "a" :: Option(7L) :: HNil
b: Int :: String :: Option[Long] :: shapeless.HNil = 2 :: a :: Some(7) :: HNil
scala> areLessThan(a, b)
res10: Boolean :: Boolean :: Boolean :: shapeless.HNil = true :: false :: true :: HNil