Last active
August 29, 2015 13:56
-
-
Save ConnorDoyle/9147037 to your computer and use it in GitHub Desktop.
Versioned
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Versioned | |
import scala.math.{ Ordered, Ordering } | |
import scala.collection.{ SortedSet, SortedSetLike } | |
trait Versioned[V <: Ordered[V]] { | |
val version: V | |
} | |
object Versioned { | |
/** | |
* Returns an ordering on type `T` derived from the natural ordering of | |
* `T`'s version type. | |
*/ | |
def versionOrdering[T <: Versioned[V], V <: Ordered[V]](): Ordering[T] = | |
Ordering.by { (item: T) => item.version } | |
} | |
// History | |
/** | |
* A sorted set of like-typed versioned elements. | |
* | |
* The natural ordering of this collection is derived from the orderedness | |
* of the elements' versions. | |
* | |
* @tparam T the type of the elements of this collection | |
* @tparam V the type of T's versions | |
*/ | |
class History[T <: Versioned[V], V <: Ordered[V]] protected ( | |
underlying: SortedSet[T] | |
) extends SortedSet[T] { | |
def this() = | |
this(SortedSet[T]()(Versioned.versionOrdering[T, V])) | |
def this(elems: Seq[T]) = | |
this(SortedSet[T](elems: _*)(Versioned.versionOrdering[T, V])) | |
def +(elem: T): History[T, V] = new History(underlying + elem) | |
def -(elem: T): History[T, V] = new History(underlying - elem) | |
def contains(elem: T): Boolean = underlying contains elem | |
def iterator: Iterator[T] = underlying.iterator | |
implicit def ordering: Ordering[T] = History.versionOrdering[T, V] | |
def rangeImpl(from: Option[T], until: Option[T]): History[T, V] = | |
new History(underlying.rangeImpl(from, until)) | |
} | |
object History { | |
def apply[T <: Versioned[V], V <: Ordered[V]](): History[T, V] = | |
new History[T, V]() | |
def apply[T <: Versioned[V], V <: Ordered[V]](elems: T*): History[T, V] = | |
new History[T, V](elems) | |
def versionOrdering[T <: Versioned[V], V <: Ordered[V]](): Ordering[T] = | |
Ordering.by { (item: T) => item.version } | |
} | |
// Usage | |
case class Timestamp(time: Long) extends Ordered[Timestamp] { | |
def compare(that: Timestamp) = this.time compare that.time | |
} | |
object Timestamp { | |
def now(): Timestamp = Timestamp(System.currentTimeMillis) | |
} | |
trait Timestamped extends Versioned[Timestamp] | |
case class Person( | |
name: String, | |
age: Int, | |
version: Timestamp = Timestamp.now | |
) extends Timestamped |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment