From 66a7a7a7c133da4d02815f77977b213f294c5dd4 Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Mon, 10 Oct 2016 17:49:30 -0400 Subject: move implicits into companion objects --- src/main/scala/com/drivergrp/core/core.scala | 10 ++++++---- src/main/scala/com/drivergrp/core/time.scala | 12 ++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/com/drivergrp/core/core.scala b/src/main/scala/com/drivergrp/core/core.scala index 158447f..a82bcc8 100644 --- a/src/main/scala/com/drivergrp/core/core.scala +++ b/src/main/scala/com/drivergrp/core/core.scala @@ -25,18 +25,20 @@ package object core { type Id[+Tag] = Long @@ Tag object Id { + implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) + implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by(i => i: Long) + def apply[Tag](value: Long) = value.asInstanceOf[Id[Tag]] } - implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) - implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by(i => i: Long) type Name[+Tag] = String @@ Tag object Name { + implicit def nameEqual[T]: Equal[Name[T]] = Equal.equal[Name[T]](_ == _) + implicit def nameOrdering[T]: Ordering[Name[T]] = Ordering.by(n => n: String) + def apply[Tag](value: String) = value.asInstanceOf[Name[Tag]] } - implicit def nameEqual[T]: Equal[Name[T]] = Equal.equal[Name[T]](_ == _) - implicit def nameOrdering[T]: Ordering[Name[T]] = Ordering.by(n => n: String) object revision { final case class Revision[T](id: String) diff --git a/src/main/scala/com/drivergrp/core/time.scala b/src/main/scala/com/drivergrp/core/time.scala index 9bafb00..e04343b 100644 --- a/src/main/scala/com/drivergrp/core/time.scala +++ b/src/main/scala/com/drivergrp/core/time.scala @@ -21,19 +21,23 @@ object time { final case class Time(millis: Long) extends AnyVal { - def isBefore(anotherTime: Time): Boolean = millis < anotherTime.millis + def isBefore(anotherTime: Time): Boolean = implicitly[Ordering[Time]].lt(this, anotherTime) - def isAfter(anotherTime: Time): Boolean = millis > anotherTime.millis + def isAfter(anotherTime: Time): Boolean = implicitly[Ordering[Time]].gt(this, anotherTime) def advanceBy(duration: Duration): Time = Time(millis + duration.toMillis) } + object Time { + + implicit def timeOrdering: Ordering[Time] = Ordering.by(_.millis) + } + + final case class TimeRange(start: Time, end: Time) { def duration: Duration = FiniteDuration(end.millis - start.millis, MILLISECONDS) } - implicit def timeOrdering: Ordering[Time] = Ordering.by(_.millis) - def startOfMonth(time: Time) = { Time(make(new GregorianCalendar()) { cal => cal.setTime(new Date(time.millis)) -- cgit v1.2.3 From aa86b5b239f29bb7b4191c5da728a87a8a6b2623 Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Mon, 10 Oct 2016 18:31:18 -0400 Subject: fix formatting --- src/main/scala/com/drivergrp/core/core.scala | 1 - src/main/scala/com/drivergrp/core/time.scala | 2 -- 2 files changed, 3 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/com/drivergrp/core/core.scala b/src/main/scala/com/drivergrp/core/core.scala index a82bcc8..1697884 100644 --- a/src/main/scala/com/drivergrp/core/core.scala +++ b/src/main/scala/com/drivergrp/core/core.scala @@ -39,7 +39,6 @@ package object core { def apply[Tag](value: String) = value.asInstanceOf[Name[Tag]] } - object revision { final case class Revision[T](id: String) diff --git a/src/main/scala/com/drivergrp/core/time.scala b/src/main/scala/com/drivergrp/core/time.scala index e04343b..032ce00 100644 --- a/src/main/scala/com/drivergrp/core/time.scala +++ b/src/main/scala/com/drivergrp/core/time.scala @@ -29,11 +29,9 @@ object time { } object Time { - implicit def timeOrdering: Ordering[Time] = Ordering.by(_.millis) } - final case class TimeRange(start: Time, end: Time) { def duration: Duration = FiniteDuration(end.millis - start.millis, MILLISECONDS) } -- cgit v1.2.3 From 1702e1c44c45e36e2d6d289ef1b7d703f65ec422 Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Tue, 11 Oct 2016 10:51:25 -0400 Subject: implicit from companion of type alias not visible (SI-9770) --- src/main/scala/com/drivergrp/core/core.scala | 11 +++++------ src/main/scala/com/drivergrp/core/time.scala | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/com/drivergrp/core/core.scala b/src/main/scala/com/drivergrp/core/core.scala index 1697884..158447f 100644 --- a/src/main/scala/com/drivergrp/core/core.scala +++ b/src/main/scala/com/drivergrp/core/core.scala @@ -25,20 +25,19 @@ package object core { type Id[+Tag] = Long @@ Tag object Id { - implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) - implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by(i => i: Long) - def apply[Tag](value: Long) = value.asInstanceOf[Id[Tag]] } + implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) + implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by(i => i: Long) type Name[+Tag] = String @@ Tag object Name { - implicit def nameEqual[T]: Equal[Name[T]] = Equal.equal[Name[T]](_ == _) - implicit def nameOrdering[T]: Ordering[Name[T]] = Ordering.by(n => n: String) - def apply[Tag](value: String) = value.asInstanceOf[Name[Tag]] } + implicit def nameEqual[T]: Equal[Name[T]] = Equal.equal[Name[T]](_ == _) + implicit def nameOrdering[T]: Ordering[Name[T]] = Ordering.by(n => n: String) + object revision { final case class Revision[T](id: String) diff --git a/src/main/scala/com/drivergrp/core/time.scala b/src/main/scala/com/drivergrp/core/time.scala index 032ce00..b935713 100644 --- a/src/main/scala/com/drivergrp/core/time.scala +++ b/src/main/scala/com/drivergrp/core/time.scala @@ -29,6 +29,7 @@ object time { } object Time { + implicit def timeOrdering: Ordering[Time] = Ordering.by(_.millis) } -- cgit v1.2.3 From f0b89933f97c73c14484643c14438d23e1723334 Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Sun, 18 Dec 2016 16:22:14 -0500 Subject: add SameId for typechecked conversion between Ids --- src/main/scala/xyz/driver/core/core.scala | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/main') diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala index 8ae9122..ce6be34 100644 --- a/src/main/scala/xyz/driver/core/core.scala +++ b/src/main/scala/xyz/driver/core/core.scala @@ -1,6 +1,7 @@ package xyz.driver import scalaz.Equal +import scala.annotation.implicitNotFound package object core { @@ -24,6 +25,24 @@ package object core { package core { + @implicitNotFound("No evidence that ${A} has the same Id as ${B}") + sealed trait SameId[A, B] { + def convert(id: Id[A]): Id[B] = Id[B](id.value) + } + + object SameId extends LowPrioritySameIdImplicits { + def apply[A, B] = new SameId[A, B] {} + + implicit def reflexive[A]: A ~ A = SameId[A, A] + implicit def symmetric[A, B](implicit ab: A ~ B): B ~ A = SameId[B, A] + } + + trait LowPrioritySameIdImplicits { + protected type ~[A, B] = SameId[A, B] + + implicit def transitive[A, B, C](implicit ab: A ~ B, bc: B ~ C): A ~ C = SameId[A, C] + } + final case class Id[+Tag](value: String) extends AnyVal { @inline def length: Int = value.length override def toString: String = value @@ -32,6 +51,12 @@ package core { object Id { implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by[Id[T], String](_.value) + + implicit class InvariantIdOps[Tag](id: Id[Tag]) { + def asId[T](implicit eq: SameId[Tag, T]): Id[T] = eq.convert(id) + } + + def sameId[A, B] = SameId[A, B] } final case class Name[+Tag](value: String) extends AnyVal { -- cgit v1.2.3 From f1c50e2cbe757926df7a94284eb0246c66394779 Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Sun, 18 Dec 2016 16:33:03 -0500 Subject: add documentation for sameId --- src/main/scala/xyz/driver/core/core.scala | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/main') diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala index ce6be34..1a6bdd7 100644 --- a/src/main/scala/xyz/driver/core/core.scala +++ b/src/main/scala/xyz/driver/core/core.scala @@ -25,6 +25,13 @@ package object core { package core { + /** + * Evidence that Id[A] can be safely converted to Id[B]. + * e.g. `implicit val CaseId = Id.sameId[Case, CasesRow]` + * if `CaseId` is in scope, we can use either of: + * `casesRowId.asId[Case]` or `caseId.asId[CasesRow]` + * Override convert for custom Id conversions. + */ @implicitNotFound("No evidence that ${A} has the same Id as ${B}") sealed trait SameId[A, B] { def convert(id: Id[A]): Id[B] = Id[B](id.value) -- cgit v1.2.3 From 415c88db0447bc94ae1624f28dcc4cc9b2d4be63 Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Sun, 18 Dec 2016 17:03:16 -0500 Subject: scope SameId to Id --- src/main/scala/xyz/driver/core/core.scala | 52 +++++++++++++++---------------- 1 file changed, 25 insertions(+), 27 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala index 1a6bdd7..c88c998 100644 --- a/src/main/scala/xyz/driver/core/core.scala +++ b/src/main/scala/xyz/driver/core/core.scala @@ -25,31 +25,6 @@ package object core { package core { - /** - * Evidence that Id[A] can be safely converted to Id[B]. - * e.g. `implicit val CaseId = Id.sameId[Case, CasesRow]` - * if `CaseId` is in scope, we can use either of: - * `casesRowId.asId[Case]` or `caseId.asId[CasesRow]` - * Override convert for custom Id conversions. - */ - @implicitNotFound("No evidence that ${A} has the same Id as ${B}") - sealed trait SameId[A, B] { - def convert(id: Id[A]): Id[B] = Id[B](id.value) - } - - object SameId extends LowPrioritySameIdImplicits { - def apply[A, B] = new SameId[A, B] {} - - implicit def reflexive[A]: A ~ A = SameId[A, A] - implicit def symmetric[A, B](implicit ab: A ~ B): B ~ A = SameId[B, A] - } - - trait LowPrioritySameIdImplicits { - protected type ~[A, B] = SameId[A, B] - - implicit def transitive[A, B, C](implicit ab: A ~ B, bc: B ~ C): A ~ C = SameId[A, C] - } - final case class Id[+Tag](value: String) extends AnyVal { @inline def length: Int = value.length override def toString: String = value @@ -59,11 +34,34 @@ package core { implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by[Id[T], String](_.value) + /** + * Evidence that Id[A] can be safely converted to Id[B]. + * e.g. `implicit val CaseId = Id.SameId[Case, CasesRow]` + * if `CaseId` is in scope, we can use either of: + * `casesRowId.asId[Case]` or `caseId.asId[CasesRow]` + * Override convert for custom Id conversions. + */ + @implicitNotFound("No evidence that ${A} has the same Id as ${B}") + sealed trait SameId[A, B] { + def convert(id: Id[A]): Id[B] = Id[B](id.value) + } + + object SameId extends LowPrioritySameIdImplicits { + def apply[A, B] = new SameId[A, B] {} + + implicit def reflexive[A]: A ~ A = SameId[A, A] + implicit def symmetric[A, B](implicit ab: A ~ B): B ~ A = SameId[B, A] + } + + trait LowPrioritySameIdImplicits { + protected type ~[A, B] = SameId[A, B] + + implicit def transitive[A, B, C](implicit ab: A ~ B, bc: B ~ C): A ~ C = SameId[A, C] + } + implicit class InvariantIdOps[Tag](id: Id[Tag]) { def asId[T](implicit eq: SameId[Tag, T]): Id[T] = eq.convert(id) } - - def sameId[A, B] = SameId[A, B] } final case class Name[+Tag](value: String) extends AnyVal { -- cgit v1.2.3 From e3c4666f718797defab28dc90a9c1912f5750223 Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Sun, 18 Dec 2016 19:28:45 -0500 Subject: remove reflexive/transitive SameId implicits --- src/main/scala/xyz/driver/core/core.scala | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala index c88c998..d1128b6 100644 --- a/src/main/scala/xyz/driver/core/core.scala +++ b/src/main/scala/xyz/driver/core/core.scala @@ -46,17 +46,9 @@ package core { def convert(id: Id[A]): Id[B] = Id[B](id.value) } - object SameId extends LowPrioritySameIdImplicits { + object SameId { def apply[A, B] = new SameId[A, B] {} - - implicit def reflexive[A]: A ~ A = SameId[A, A] - implicit def symmetric[A, B](implicit ab: A ~ B): B ~ A = SameId[B, A] - } - - trait LowPrioritySameIdImplicits { - protected type ~[A, B] = SameId[A, B] - - implicit def transitive[A, B, C](implicit ab: A ~ B, bc: B ~ C): A ~ C = SameId[A, C] + implicit def symmetric[A, B](implicit ab: SameId[A, B]): SameId[B, A] = SameId[B, A] } implicit class InvariantIdOps[Tag](id: Id[Tag]) { -- cgit v1.2.3 From aca1f9c10b89499b073046d9b50fa455b675e20e Mon Sep 17 00:00:00 2001 From: Stewart Stewart Date: Sun, 18 Dec 2016 19:37:53 -0500 Subject: use implicit mappers for typed Id conversion --- src/main/scala/xyz/driver/core/core.scala | 22 ++-------------------- src/test/scala/xyz/driver/core/CoreTest.scala | 15 +++++++++------ 2 files changed, 11 insertions(+), 26 deletions(-) (limited to 'src/main') diff --git a/src/main/scala/xyz/driver/core/core.scala b/src/main/scala/xyz/driver/core/core.scala index d1128b6..783150a 100644 --- a/src/main/scala/xyz/driver/core/core.scala +++ b/src/main/scala/xyz/driver/core/core.scala @@ -1,7 +1,6 @@ package xyz.driver import scalaz.Equal -import scala.annotation.implicitNotFound package object core { @@ -34,25 +33,8 @@ package core { implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by[Id[T], String](_.value) - /** - * Evidence that Id[A] can be safely converted to Id[B]. - * e.g. `implicit val CaseId = Id.SameId[Case, CasesRow]` - * if `CaseId` is in scope, we can use either of: - * `casesRowId.asId[Case]` or `caseId.asId[CasesRow]` - * Override convert for custom Id conversions. - */ - @implicitNotFound("No evidence that ${A} has the same Id as ${B}") - sealed trait SameId[A, B] { - def convert(id: Id[A]): Id[B] = Id[B](id.value) - } - - object SameId { - def apply[A, B] = new SameId[A, B] {} - implicit def symmetric[A, B](implicit ab: SameId[A, B]): SameId[B, A] = SameId[B, A] - } - - implicit class InvariantIdOps[Tag](id: Id[Tag]) { - def asId[T](implicit eq: SameId[Tag, T]): Id[T] = eq.convert(id) + object Mapper { + def apply[A, B]: (Id[A] => Id[B]) = (id: Id[A]) => Id[B](id.value) } } diff --git a/src/test/scala/xyz/driver/core/CoreTest.scala b/src/test/scala/xyz/driver/core/CoreTest.scala index 1ccd707..72b6bc6 100644 --- a/src/test/scala/xyz/driver/core/CoreTest.scala +++ b/src/test/scala/xyz/driver/core/CoreTest.scala @@ -44,14 +44,17 @@ class CoreTest extends FlatSpec with Matchers with MockitoSugar { final case class Y(id: Id[Y]) final case class Z(id: Id[Z]) - implicit val xy = Id.SameId[X,Y] - implicit val yz = Id.SameId[Y,Z] + implicit val xy = Id.Mapper[X,Y] + implicit val yx = Id.Mapper[Y,X] + implicit val yz = Id.Mapper[Y,Z] + implicit val zy = Id.Mapper[Z,Y] val x = X(Id("0")) - val y = Y(x.id.asId[Y]) - val z = Z(y.id.asId[Z]) - val y2 = Y(z.id.asId[Y]) - val x2 = X(z.id.asId[Y].asId[X]) + val y = Y(x.id) + val z = Z(y.id) + val y2 = Y(z.id) + val x2 = X(y2.id) + x2 === x y2 === y } -- cgit v1.2.3