我想创建一个Array(或List,ArrayBuffer等),它只能包含具有已定义隐式排序的类的实例(例如Int,Long,Double)。
这样的事情:
val ab = new ArrayBuffer[???]()
ab += 7
ab += 8.9
ab += 8L
我不想将这些值相互比较。
答案 0 :(得分:1)
只需使用类型类约束,如下所示
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
作为参数
scala> implicit val orderingCat: Ordering[Cat] = (a: Cat, b: Cat) => ???
orderingCat: Ordering[Cat] = $anonfun$1@6be766d1
scala> createList(Cat())
res4: List[Cat] = List(Cat())
有效。
答案 1 :(得分:0)
如果你真的想拥有一个不同类型的对象列表,并且仍然能够在编译时静态检查该列表中对象的内容,那么你必须使用来自{{HList
的内容。 3}}。下面是一个示例,说明如何使用两个异构列表并在编译时检查两个列表中的每个i th 元素是否可以相互比较。
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