Scala收集具有隐式排序的类



我想创建一个数组(或列表,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

相关内容

  • 没有找到相关文章

最新更新