Sorted predicates
mhriemers opened this issue · 1 comments
mhriemers commented
As discussed in #6, there is room for a Sorted
predicate. I'm currently running into use cases where an algorithm's implementation differs for sorted and unsorted collections. If we can decide on a type signature, I can start with the implementation. With regards to the sort direction, in my opinion we can do two things:
- we can just assume ascending.
- we can provide some sort of enum type which describes the direction.
I'd like to hear opinions on this. Also, our implicit Validate
will need some sort of (implicit) Ordering
to decide if the collection is sorted or not.
mhriemers commented
This what I could come-up with so far:
final case class Sorted[D <: SortDirection](d: D)
sealed trait SortDirection {
def ascending: Boolean
}
implicit case object Ascending extends SortDirection {
override def ascending: Boolean = true
}
implicit case object Descending extends SortDirection {
override def ascending: Boolean = false
}
type Asc = Ascending.type
type Desc = Descending.type
object Sorted {
implicit def sortedValidate[A, I[a] <: Iterable[a], D <: SortDirection](implicit
d: D,
ord: Ordering[A]): Validate.Plain[I[A], Sorted[D]] =
Validate.fromPredicate(i ⇒ {
val tuples = i.dropRight(1).zip(i.tail)
val f = if (d.ascending) ord.lteq _ else ord.gteq _
tuples.forall(f.tupled)
}, i ⇒ {
val tuples = i.dropRight(1).zip(i.tail)
val sign = if (d.ascending) "<=" else ">="
tuples.map {
case (a, b) ⇒ s"$a $sign $b"
}.mkString("(", " && ", ")")
}, Sorted(d))
}
Let me know what you guys think. This could be more generalized to Traversable[A]
but I didn't have time to figure that out yet.