简体   繁体   中英

Scala Ordering[T] and Serializable

Given a case class like this:

case class KVPair[
    K <: Ordering[K] with Serializable, 
    VV <: Serializable
](key: K, value: VV)

How would I go about constructing a KVPair with Longs , something like this:

def createKVPair(): KVPair[Long, Long] = {
    KVPair(1L, 1L)
}

The compiler keeps complaining with:

Long does not conform to method apply's type parameter bounds.

There are 2 things going on here. First of all Long does not extend Ordering[Long] . The page you linked from the docs in the comments is the documentation of an implicit object called Long in the scala.math.Ordering package.

However, that object is very relevant here. Since that object is in implicit scope, you can use a context bound to ensure that there is an instance of Ordered[Long] is available, which will allow code to order your Longs .

case class Key[K : Ordering](key: K)

This will allow you to do Key(1L) .

Your other problem is that Long is also not Serializable , so the second generic parameter is also problematic. Long is implicitly viewable as a java.io.Serializable , which might be of interest to you here. You can use a view bound to ensure that K and V have this constraint:

type JS = java.io.Serializable
case class KVPair[K <% JS : Ordering, V <% JS](key: K, value: V)

The context-bound and view-bound syntax make this equivalent to:

 case class KVPair[K, V](key: K, value: V)(
    implicit kev1: Ordering[K], 
             kev2: K => JS, 
             vev1: V => JS
 )

You can read more about context bounds and view bounds on this answer .

scala.Long is not an Ordering . The type bound K <: Ordering[K] means K should must be bounded by the Ordering type. And scala.Long most certainly does not extend the type class Ordering . There exists an instance of an Ordering[Long] , but scala.Long does not extend it.

What you want is evidence of an Ordering[K] , ie., a context bound . Something like this:

case class KVPair[K : Ordering , VV](key: K, value: VV)

def createKVPair(): KVPair[Long, Long] = {
    KVPair(1L, 1L)
}

The above case class is syntactic sugar for:

case class KVPair[K, VV](key: K, value: VV)(implicit ev: Ordering[K])

You may have noticed that I've also removed the Serializable bound. This is because Long is not Serializable , so it cannot possibly work with that constraint.

scala> implicitly[Long <:< Serializable]
<console>:26: error: Cannot prove that Long <:< Serializable.
              implicitly[Long <:< Serializable]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM