Skip to content

Instantly share code, notes, and snippets.

@echeipesh
Last active August 29, 2015 14:22
Show Gist options
  • Save echeipesh/5457150b92606723d30e to your computer and use it in GitHub Desktop.
Save echeipesh/5457150b92606723d30e to your computer and use it in GitHub Desktop.
Shapeless Ordering
package org.example
import shapeless._
import shapeless.ops.hlist._
object Min extends Poly1 {
implicit def tuple[C] = at[((C, C), Ordering[C])]{ case ((c1, c2), ord) => ord.min(c1, c2) }
}
object Max extends Poly1 {
implicit def tuple[C] = at[((C, C), Ordering[C])]{ case ((c1, c2), ord) => ord.max(c1, c2) }
}
object FindOrdering extends Poly1 {
implicit def tuple[T](implicit ord: Ordering[T]) = at[T]{ _ => ord }
}
case class Bounded[A <: HList, O <: HList, Z1 <: HList, Z2 <: HList](min: A, max: A, orderings: O)
(implicit
ev0: Mapped.Aux[A, Ordering, O],
ev1: Zip.Aux[A::A::HNil, Z1],
ev2: Zip.Aux[Z1::O::HNil, Z2],
ev3: Mapper.Aux[Min.type, Z2, A],
ev4: Mapper.Aux[Max.type, Z2, A]
) {
def combine(a: A): Bounded[A, O, Z1, Z2] =
new Bounded(
a zip min zip orderings map Min,
a zip max zip orderings map Max,
orderings
)
def combine(hb: Bounded[A, O, Z1, Z2]): Bounded[A, O, Z1, Z2] =
new Bounded(
hb.min zip min zip orderings map Min,
hb.max zip max zip orderings map Max,
orderings
)
}
case class OBounded[A <: HList, O <: HList, Z1 <: HList, Z2 <: HList](min: A, max: A)
(implicit
ev1: Zip.Aux[A::A::HNil, Z1],
ev2: Mapper.Aux[FindOrdering.type, A, O],
ev3: Zip.Aux[Z1::O::HNil, Z2],
ev4: Mapper.Aux[Min.type, Z2, A],
ev5: Mapper.Aux[Max.type, Z2, A]
) {
def combine(a: A): OBounded[A, O, Z1, Z2] = {
val orderings: O = min map FindOrdering
new OBounded(
a zip min zip orderings map Min,
a zip max zip orderings map Max
)
}
def combine(hb: OBounded[A, O, Z1, Z2]): OBounded[A, O, Z1, Z2] = {
val orderings: O = min map FindOrdering
new OBounded(
hb.min zip min zip orderings map Min,
hb.max zip max zip orderings map Max
)
}
}
import org.scalatest._
import shapeless._
class BoundedSpec extends FunSpec {
describe("Hlist"){
it("should require orderings"){
val a1 = 2.0 :: 1 :: HNil
val a2 = 1.0 :: 2 :: HNil
val a3 = 3.0 :: 1 :: HNil
val orderings = Ordering[Double] :: Ordering[Int] :: HNil
info(s"${a1.tupled}")
val b1 = new Bounded(a1, a2, orderings)
info(s"b1 = $b1")
info(s"b1.combine(a3) = ${b1.combine(a3)}")
val b2 = new Bounded(a1, a1, orderings)
info(s"b1.combine(b2) = ${b1.combine(b2)}")
info(s"b2.combine(b1) = ${b2.combine(b1)}")
}
it("should find orderings for itself"){
val a1 = 2.0 :: 1 :: HNil
val a2 = 1.0 :: 2 :: HNil
val a3 = 3.0 :: 1 :: HNil
info(s"FindOrder =${a1 map FindOrdering}")
info(s"${a1.tupled}")
val b1 = new OBounded(a1, a2)
info(s"b1 = $b1")
info(s"b1.combine(a3) = ${b1.combine(a3)}")
val b2 = new OBounded(a1, a1)
info(s"b1.combine(b2) = ${b1.combine(b2)}")
info(s"b2.combine(b1) = ${b2.combine(b1)}")
}
}
}
import shapeless._
import shapeless.ops.hlist._
object FindOrdering extends Poly1 {
implicit def tuple[T](implicit ord: Ordering[T]) = at[T]{ _ => ord }
}
val a1 = 2.0 :: 1 :: HNil
// Double :: Int :: HNil
a1 map FindOrdering
// scala.math.Ordering$Double$@3955ec13 :: scala.math.Ordering$Int$@37fdf0cd :: HNil
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment