Skip to content

Instantly share code, notes, and snippets.

@atamborrino
Last active September 7, 2017 10:05
Show Gist options
  • Save atamborrino/30a24612411445eb15acbde98c0c2d25 to your computer and use it in GitHub Desktop.
Save atamborrino/30a24612411445eb15acbde98c0c2d25 to your computer and use it in GitHub Desktop.
Timed type class + implicit derivation to Order type class via Natural Transformation
import java.time.Instant
import shapeless._
import simulacrum._
import scala.concurrent.duration.FiniteDuration
import scala.language.implicitConversions
import scala.concurrent.duration._
@typeclass
trait Timed[A] {
def getInstant(a: A): Instant
def setInstant(a: A, instant: Instant): A
@op(">>") def shift(a: A, duration: Duration): A = setInstant(a, getInstant(a).plusMillis(duration.toMillis))
@op("<<") def reverseShift(a: A, duration: Duration): A = setInstant(a, getInstant(a).minusMillis(duration.toMillis))
def distance(a: A, b: A): FiniteDuration = Math.abs(getInstant(a).toEpochMilli - getInstant(b).toEpochMilli).millis
}
object Timed {
import Timed.ops._
implicit val timedForInstant = new Timed[Instant] {
def getInstant(a: Instant): Instant = a
def setInstant(a: Instant, instant: Instant): Instant = instant
}
// HList's head must be Timed
implicit def timedForHlist[H: Timed, T <: HList]: Timed[H :: T] = new Timed[H :: T] {
def getInstant(a: H :: T): Instant = a.head.getInstant
def setInstant(a: H :: T, instant: Instant): H :: T = a match {
case head :: tail => head.setInstant(instant) :: tail
}
}
implicit def timedForGeneric[A, Repr <: HList](implicit gen: Generic.Aux[A, Repr], timed: Timed[Repr]): Timed[A] =
new Timed[A] {
def getInstant(a: A): Instant = gen.to(a).getInstant
def setInstant(a: A, instant: Instant): A = gen.from(gen.to(a).setInstant(instant))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment