From 14dd0e67fc965b804d92bb5774b0d1f3ab6aa7a0 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Fri, 8 Jul 2016 23:44:40 +0200 Subject: [PATCH 01/16] WIP --- .../scala/eu/timepit/refined/api/Unpack.scala | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala b/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala new file mode 100644 index 000000000..dbcb67807 --- /dev/null +++ b/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala @@ -0,0 +1,50 @@ +package eu.timepit.refined +package api + + +trait RefineOps[FTP] { + def refine[T](t: T)(implicit u: Unpack[T, FTP]): Either[String, FTP] = + u.refType.refine(t)(u.validate).right.map(u.subst2) + + def refineM[F[_, _], T, P](t: T)(implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P]): FTP = macro macros.RefineMacro.implApplyRef[FTP, F, T, P] +} + +object RefineOps { + def apply[FTP]: RefineOps[FTP] = new RefineOps[FTP] {} +} + +trait Unpack[T, FTP] { + type F[_, _] + type P + + def refType: RefType[F] + def validate: Validate[T, P] + + def subst: FTP => F[T, P] + def subst2: F[T, P] => FTP +} + +object Unpack { + + def apply[T, FTP](implicit u: Unpack[T, FTP]): Aux[T, FTP, u.F, u.P] = u + + type Aux[T, FTP, F0[_, _], P0] = Unpack[T, FTP] { + type F[x, y] = F0[x, y] + type P = P0 + } + + implicit def instance[T, F0[_, _], P0]( + implicit + rt: RefType[F0], v: Validate[T, P0] + ): Aux[T, F0[T, P0], F0, P0] = + new Unpack[T, F0[T, P0]] { + override type F[x, y] = F0[x, y] + override type P = P0 + + override def refType: RefType[F] = rt + override def validate: Validate[T, P] = v + + override def subst: F0[T, P0] => F[T, P] = identity + override def subst2: F[T, P] => F0[T, P0] = identity + } +} From 7dbf8fe3e671496516fa36a788c56ac774729941 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Mon, 18 Jul 2016 22:02:48 +0200 Subject: [PATCH 02/16] WIP --- .../scala/eu/timepit/refined/api/Unpack.scala | 40 ++++++++++++------- .../internal/ApplyRefPartiallyApplied.scala | 5 ++- .../scala/eu/timepit/refined/package.scala | 5 ++- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala b/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala index dbcb67807..229c2453c 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala @@ -1,10 +1,15 @@ package eu.timepit.refined package api - trait RefineOps[FTP] { - def refine[T](t: T)(implicit u: Unpack[T, FTP]): Either[String, FTP] = - u.refType.refine(t)(u.validate).right.map(u.subst2) + def refine[T](t: T)(implicit u: Unpack.AuxT[FTP, T]): Either[String, FTP] = + u.refType.refine(t)(u.validate).right.map(u.pack) + + def refine2[F[_, _], T, P](t: T)(implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P]): Either[String, FTP] = + rt.refine[P](t).right.map(ev) + + def refineUnsafe[T](t: T)(implicit u: Unpack.AuxT[FTP, T]): FTP = + u.pack(u.refType.refine.unsafeFrom(t)(u.validate)) def refineM[F[_, _], T, P](t: T)(implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P]): FTP = macro macros.RefineMacro.implApplyRef[FTP, F, T, P] } @@ -13,38 +18,45 @@ object RefineOps { def apply[FTP]: RefineOps[FTP] = new RefineOps[FTP] {} } -trait Unpack[T, FTP] { +object Natural extends RefineOps[Natural] + +trait Unpack[FTP] { type F[_, _] + type T type P def refType: RefType[F] def validate: Validate[T, P] - def subst: FTP => F[T, P] - def subst2: F[T, P] => FTP + def pack: F[T, P] =:= FTP } object Unpack { - def apply[T, FTP](implicit u: Unpack[T, FTP]): Aux[T, FTP, u.F, u.P] = u + def apply[FTP](implicit u: Unpack[FTP]): Aux[FTP, u.F, u.T, u.P] = u - type Aux[T, FTP, F0[_, _], P0] = Unpack[T, FTP] { + type Aux[FTP, F0[_, _], T0, P0] = Unpack[FTP] { type F[x, y] = F0[x, y] + type T = T0 type P = P0 } - implicit def instance[T, F0[_, _], P0]( + type AuxT[FTP, T0] = Unpack[FTP] { + type T = T0 + } + + implicit def instance[F0[_, _], T0, P0]( implicit - rt: RefType[F0], v: Validate[T, P0] - ): Aux[T, F0[T, P0], F0, P0] = - new Unpack[T, F0[T, P0]] { + rt: RefType[F0], v: Validate[T0, P0] + ): Aux[F0[T0, P0], F0, T0, P0] = + new Unpack[F0[T0, P0]] { override type F[x, y] = F0[x, y] + override type T = T0 override type P = P0 override def refType: RefType[F] = rt override def validate: Validate[T, P] = v - override def subst: F0[T, P0] => F[T, P] = identity - override def subst2: F[T, P] => F0[T, P0] = identity + override def pack: F[T, P] =:= F0[T, P0] = implicitly } } diff --git a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala index 94583a6c9..abe8064af 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala @@ -1,7 +1,7 @@ package eu.timepit.refined package internal -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.{ RefType, Unpack, Validate } /** * Helper class that allows the types `F`, `T`, and `P` to be inferred @@ -18,6 +18,9 @@ final class ApplyRefPartiallyApplied[FTP] { ): Either[String, FTP] = rt.refine[P](t).right.map(ev) + def apply2[T](t: T)(implicit u: Unpack.AuxT[FTP, T]): Either[String, FTP] = + u.refType.refine[u.P](t)(u.validate).right.map(u.pack) + def unsafeFrom[F[_, _], T, P](t: T)( implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P] diff --git a/core/shared/src/main/scala/eu/timepit/refined/package.scala b/core/shared/src/main/scala/eu/timepit/refined/package.scala index b81940016..b2dd79d78 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/package.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/package.scala @@ -1,11 +1,14 @@ package eu.timepit -import eu.timepit.refined.api.{ Refined, RefType } +import eu.timepit.refined.api.{ RefType, Refined } import eu.timepit.refined.internal._ +import eu.timepit.refined.numeric.NonNegative import shapeless.tag.@@ package object refined { + type Natural = Int Refined NonNegative + /** * Alias for `shapeless.Witness` that provides concise syntax for * literal-based singleton types. From 7cf4293cd12d5d04056f78e6fa8c3ab2b578dc0a Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Wed, 20 Jul 2016 23:40:51 +0200 Subject: [PATCH 03/16] WIP3 --- .../src/main/scala/eu/timepit/refined/api/Unpack.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala b/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala index 229c2453c..bb400cf16 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala @@ -3,7 +3,10 @@ package api trait RefineOps[FTP] { def refine[T](t: T)(implicit u: Unpack.AuxT[FTP, T]): Either[String, FTP] = - u.refType.refine(t)(u.validate).right.map(u.pack) + u.refine(t) + + def refine3[T](implicit u: Unpack.AuxT[FTP, _]): T => Either[String, FTP] = + (t) => u.refine(t).asInstanceOf def refine2[F[_, _], T, P](t: T)(implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P]): Either[String, FTP] = rt.refine[P](t).right.map(ev) @@ -29,6 +32,9 @@ trait Unpack[FTP] { def validate: Validate[T, P] def pack: F[T, P] =:= FTP + + def refine(t: T): Either[String, FTP] = + refType.refine[P](t)(validate).right.map(pack) } object Unpack { From 276957d88976b6696f0bf7036ed9dfc83ded1ba8 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 24 Jul 2016 15:09:25 +0200 Subject: [PATCH 04/16] WIP --- .../eu/timepit/refined/api/RefinedType.scala | 55 +++++++++++++++ .../scala/eu/timepit/refined/api/Unpack.scala | 68 ------------------- .../internal/ApplyRefPartiallyApplied.scala | 5 +- 3 files changed, 56 insertions(+), 72 deletions(-) create mode 100644 core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala delete mode 100644 core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala new file mode 100644 index 000000000..3898ebf7d --- /dev/null +++ b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala @@ -0,0 +1,55 @@ +package eu.timepit.refined +package api + +trait RefinedType[FTP] { + type F[_, _] + type T + type P + + def refType: RefType[F] + + def validate: Validate[T, P] + + def subst1: F[T, P] =:= FTP + + def subst2: FTP =:= F[T, P] + + def refine(t: T): Either[String, FTP] = ??? + + def refineUnsafe(t: T): FTP = ??? + + def refineM(t: T): FTP = ??? +} + +object RefinedType { + + def apply[FTP](implicit rt: RefinedType[FTP]): Aux[FTP, rt.F, rt.T, rt.P] = rt + + type Aux[FTP, F0[_, _], T0, P0] = RefinedType[FTP] { + type F[x, y] = F0[x, y] + type T = T0 + type P = P0 + } + + type AuxT[FTP, T0] = RefinedType[FTP] { + type T = T0 + } + + implicit def instance[F0[_, _], T0, P0]( + implicit + rt: RefType[F0], v: Validate[T0, P0] + ): Aux[F0[T0, P0], F0, T0, P0] = + new RefinedType[F0[T0, P0]] { + override type F[x, y] = F0[x, y] + override type T = T0 + override type P = P0 + + override def refType: RefType[F] = rt + + override def validate: Validate[T, P] = v + + override def subst1: F[T, P] =:= F0[T, P0] = implicitly + + override def subst2: F0[T0, P0] =:= F[T, P] = implicitly + } +} diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala b/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala deleted file mode 100644 index bb400cf16..000000000 --- a/core/shared/src/main/scala/eu/timepit/refined/api/Unpack.scala +++ /dev/null @@ -1,68 +0,0 @@ -package eu.timepit.refined -package api - -trait RefineOps[FTP] { - def refine[T](t: T)(implicit u: Unpack.AuxT[FTP, T]): Either[String, FTP] = - u.refine(t) - - def refine3[T](implicit u: Unpack.AuxT[FTP, _]): T => Either[String, FTP] = - (t) => u.refine(t).asInstanceOf - - def refine2[F[_, _], T, P](t: T)(implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P]): Either[String, FTP] = - rt.refine[P](t).right.map(ev) - - def refineUnsafe[T](t: T)(implicit u: Unpack.AuxT[FTP, T]): FTP = - u.pack(u.refType.refine.unsafeFrom(t)(u.validate)) - - def refineM[F[_, _], T, P](t: T)(implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P]): FTP = macro macros.RefineMacro.implApplyRef[FTP, F, T, P] -} - -object RefineOps { - def apply[FTP]: RefineOps[FTP] = new RefineOps[FTP] {} -} - -object Natural extends RefineOps[Natural] - -trait Unpack[FTP] { - type F[_, _] - type T - type P - - def refType: RefType[F] - def validate: Validate[T, P] - - def pack: F[T, P] =:= FTP - - def refine(t: T): Either[String, FTP] = - refType.refine[P](t)(validate).right.map(pack) -} - -object Unpack { - - def apply[FTP](implicit u: Unpack[FTP]): Aux[FTP, u.F, u.T, u.P] = u - - type Aux[FTP, F0[_, _], T0, P0] = Unpack[FTP] { - type F[x, y] = F0[x, y] - type T = T0 - type P = P0 - } - - type AuxT[FTP, T0] = Unpack[FTP] { - type T = T0 - } - - implicit def instance[F0[_, _], T0, P0]( - implicit - rt: RefType[F0], v: Validate[T0, P0] - ): Aux[F0[T0, P0], F0, T0, P0] = - new Unpack[F0[T0, P0]] { - override type F[x, y] = F0[x, y] - override type T = T0 - override type P = P0 - - override def refType: RefType[F] = rt - override def validate: Validate[T, P] = v - - override def pack: F[T, P] =:= F0[T, P0] = implicitly - } -} diff --git a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala index abe8064af..94583a6c9 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala @@ -1,7 +1,7 @@ package eu.timepit.refined package internal -import eu.timepit.refined.api.{ RefType, Unpack, Validate } +import eu.timepit.refined.api.{ RefType, Validate } /** * Helper class that allows the types `F`, `T`, and `P` to be inferred @@ -18,9 +18,6 @@ final class ApplyRefPartiallyApplied[FTP] { ): Either[String, FTP] = rt.refine[P](t).right.map(ev) - def apply2[T](t: T)(implicit u: Unpack.AuxT[FTP, T]): Either[String, FTP] = - u.refType.refine[u.P](t)(u.validate).right.map(u.pack) - def unsafeFrom[F[_, _], T, P](t: T)( implicit ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P] From 79f346fcd9c805ae7e1f542cc1fa0e99a2d2c7eb Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 24 Jul 2016 15:11:09 +0200 Subject: [PATCH 05/16] WIP --- core/shared/src/main/scala/eu/timepit/refined/package.scala | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/shared/src/main/scala/eu/timepit/refined/package.scala b/core/shared/src/main/scala/eu/timepit/refined/package.scala index b2dd79d78..b81940016 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/package.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/package.scala @@ -1,14 +1,11 @@ package eu.timepit -import eu.timepit.refined.api.{ RefType, Refined } +import eu.timepit.refined.api.{ Refined, RefType } import eu.timepit.refined.internal._ -import eu.timepit.refined.numeric.NonNegative import shapeless.tag.@@ package object refined { - type Natural = Int Refined NonNegative - /** * Alias for `shapeless.Witness` that provides concise syntax for * literal-based singleton types. From 7ddd5e3b0ea58a09668dc824343cebdf7dbd37c0 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Sun, 24 Jul 2016 23:56:08 +0200 Subject: [PATCH 06/16] WIP --- .../eu/timepit/refined/api/RefinedType.scala | 30 ++++++++++++------- .../internal/ApplyRefMPartiallyApplied.scala | 8 ++--- .../internal/ApplyRefPartiallyApplied.scala | 20 +++++-------- .../internal/RefineMFullyApplied.scala | 7 +++-- .../internal/RefineMPartiallyApplied.scala | 7 +++-- .../internal/RefinePartiallyApplied.scala | 11 +++---- .../timepit/refined/macros/RefineMacro.scala | 17 +++++++++++ 7 files changed, 61 insertions(+), 39 deletions(-) diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala index 3898ebf7d..2a900cb72 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala @@ -6,19 +6,27 @@ trait RefinedType[FTP] { type T type P - def refType: RefType[F] + val refType: RefType[F] - def validate: Validate[T, P] + val validate: Validate[T, P] - def subst1: F[T, P] =:= FTP + val subst1: F[T, P] =:= FTP - def subst2: FTP =:= F[T, P] + val subst2: FTP =:= F[T, P] - def refine(t: T): Either[String, FTP] = ??? + def refine(t: T): Either[String, FTP] = { + val res = validate.validate(t) + if (res.isPassed) Right(subst1(refType.unsafeWrap(t))) + else Left(validate.showResult(t, res)) + } - def refineUnsafe(t: T): FTP = ??? + def refineUnsafe(t: T): FTP = + refine(t).fold(err => throw new IllegalArgumentException(err), identity) - def refineM(t: T): FTP = ??? + def refineM(t: T)( + implicit + rt: RefinedType.AuxT[FTP, T] + ): FTP = macro macros.RefineMacro.refineImpl[FTP, T, P] } object RefinedType { @@ -44,12 +52,12 @@ object RefinedType { override type T = T0 override type P = P0 - override def refType: RefType[F] = rt + override val refType: RefType[F] = rt - override def validate: Validate[T, P] = v + override val validate: Validate[T, P] = v - override def subst1: F[T, P] =:= F0[T, P0] = implicitly + override val subst1: F[T, P] =:= F0[T, P0] = implicitly - override def subst2: F0[T0, P0] =:= F[T, P] = implicitly + override val subst2: F0[T0, P0] =:= F[T, P] = implicitly } } diff --git a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefMPartiallyApplied.scala b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefMPartiallyApplied.scala index 611160329..6d7d75a28 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefMPartiallyApplied.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefMPartiallyApplied.scala @@ -1,7 +1,7 @@ package eu.timepit.refined package internal -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.RefinedType /** * Helper class that allows the types `F`, `T`, and `P` to be inferred @@ -12,8 +12,8 @@ import eu.timepit.refined.api.{ RefType, Validate } */ final class ApplyRefMPartiallyApplied[FTP] { - def apply[F[_, _], T, P](t: T)( + def apply[T](t: T)( implicit - ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P] - ): FTP = macro macros.RefineMacro.implApplyRef[FTP, F, T, P] + rt: RefinedType.AuxT[FTP, T] + ): FTP = macro macros.RefineMacro.refineImpl[FTP, T, rt.P] } diff --git a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala index 94583a6c9..44e082cf7 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/internal/ApplyRefPartiallyApplied.scala @@ -1,26 +1,20 @@ package eu.timepit.refined package internal -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.RefinedType /** - * Helper class that allows the types `F`, `T`, and `P` to be inferred - * from calls like `[[api.RefType.applyRef]][F[T, P]](t)`. + * Helper class that allows the type `T` to be inferred from calls like + * `[[api.RefType.applyRef]][F[T, P]](t)`. * * See [[http://tpolecat.github.io/2015/07/30/infer.html]] for a detailed * explanation of this trick. */ final class ApplyRefPartiallyApplied[FTP] { - def apply[F[_, _], T, P](t: T)( - implicit - ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P] - ): Either[String, FTP] = - rt.refine[P](t).right.map(ev) + def apply[T](t: T)(implicit rt: RefinedType.AuxT[FTP, T]): Either[String, FTP] = + rt.refine(t) - def unsafeFrom[F[_, _], T, P](t: T)( - implicit - ev: F[T, P] =:= FTP, rt: RefType[F], v: Validate[T, P] - ): FTP = - ev(rt.refine[P].unsafeFrom(t)) + def unsafeFrom[T](t: T)(implicit rt: RefinedType.AuxT[FTP, T]): FTP = + rt.refineUnsafe(t) } diff --git a/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMFullyApplied.scala b/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMFullyApplied.scala index 489480af5..407639b85 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMFullyApplied.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMFullyApplied.scala @@ -1,10 +1,13 @@ package eu.timepit.refined package internal -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.RefinedType import eu.timepit.refined.macros.RefineMacro final class RefineMFullyApplied[F[_, _], T, P] { - def apply(t: T)(implicit rt: RefType[F], v: Validate[T, P]): F[T, P] = macro RefineMacro.impl[F, T, P] + def apply(t: T)( + implicit + rt: RefinedType.AuxT[F[T, P], T] + ): F[T, P] = macro RefineMacro.refineImpl[F[T, P], T, P] } diff --git a/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMPartiallyApplied.scala b/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMPartiallyApplied.scala index f4abb1a26..9dd865ef7 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMPartiallyApplied.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/internal/RefineMPartiallyApplied.scala @@ -1,7 +1,7 @@ package eu.timepit.refined package internal -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.RefinedType import eu.timepit.refined.macros.RefineMacro /** @@ -13,5 +13,8 @@ import eu.timepit.refined.macros.RefineMacro */ final class RefineMPartiallyApplied[F[_, _], P] { - def apply[T](t: T)(implicit rt: RefType[F], v: Validate[T, P]): F[T, P] = macro RefineMacro.impl[F, T, P] + def apply[T](t: T)( + implicit + rt: RefinedType.AuxT[F[T, P], T] + ): F[T, P] = macro RefineMacro.refineImpl[F[T, P], T, P] } diff --git a/core/shared/src/main/scala/eu/timepit/refined/internal/RefinePartiallyApplied.scala b/core/shared/src/main/scala/eu/timepit/refined/internal/RefinePartiallyApplied.scala index 6f3ea5c3d..f632aa847 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/internal/RefinePartiallyApplied.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/internal/RefinePartiallyApplied.scala @@ -1,7 +1,7 @@ package eu.timepit.refined package internal -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.{ RefinedType, RefType, Validate } /** * Helper class that allows the type `T` to be inferred from calls like @@ -12,14 +12,11 @@ import eu.timepit.refined.api.{ RefType, Validate } */ final class RefinePartiallyApplied[F[_, _], P](rt: RefType[F]) { - def apply[T](t: T)(implicit v: Validate[T, P]): Either[String, F[T, P]] = { - val res = v.validate(t) - if (res.isPassed) Right(rt.unsafeWrap(t)) - else Left(v.showResult(t, res)) - } + def apply[T](t: T)(implicit v: Validate[T, P]): Either[String, F[T, P]] = + RefinedType.instance(rt, v).refine(t) def unsafeFrom[T](t: T)(implicit v: Validate[T, P]): F[T, P] = - apply(t).fold(err => throw new IllegalArgumentException(err), identity) + RefinedType.instance(rt, v).refineUnsafe(t) @deprecated("force has been renamed to unsafeFrom", "0.5.0") def force[T](t: T)(implicit v: Validate[T, P]): F[T, P] = diff --git a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala index f12adf631..da33a77a7 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala @@ -33,4 +33,21 @@ class RefineMacro(val c: blackbox.Context) extends MacroUtils { ev: c.Expr[F[T, P] =:= FTP], rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] ): c.Expr[FTP] = c.Expr(impl(t)(rt, v).tree) + + def refineImpl[FTP, T: c.WeakTypeTag, P: c.WeakTypeTag](t: c.Expr[T])( + rt: c.Expr[api.RefinedType.AuxT[FTP, T]] + ): c.Expr[FTP] = { + val tValue: T = t.tree match { + case Literal(Constant(value)) => value.asInstanceOf[T] + case _ => abort(Resources.refineNonCompileTimeConstant) + } + + val refinedType = eval(rt) + val res = refinedType.validate.validate(tValue) + if (res.isFailed) { + abort(refinedType.validate.showResult(tValue, res)) + } + + c.Expr[FTP](refinedType.refType.unsafeWrapM[T, P](c)(t).tree) + } } From d74e375ddf83338a8daaf1951f80e960fd75158b Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Mon, 25 Jul 2016 00:02:18 +0200 Subject: [PATCH 07/16] wip --- .../src/main/scala/eu/timepit/refined/api/RefinedType.scala | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala index 2a900cb72..09c248178 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala @@ -53,11 +53,8 @@ object RefinedType { override type P = P0 override val refType: RefType[F] = rt - override val validate: Validate[T, P] = v - override val subst1: F[T, P] =:= F0[T, P0] = implicitly - override val subst2: F0[T0, P0] =:= F[T, P] = implicitly } } From 91e3da5a2eea8109c759e87aa8958e208ec686e8 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Mon, 25 Jul 2016 18:34:10 +0200 Subject: [PATCH 08/16] Simplify refTypeCodec --- .../eu/timepit/refined/scodec/package.scala | 18 +++++++++--------- .../eu/timepit/refined/api/RefinedType.scala | 3 +++ .../eu/timepit/refined/api/RefTypeSpec.scala | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/contrib/scodec/shared/src/main/scala/eu/timepit/refined/scodec/package.scala b/contrib/scodec/shared/src/main/scala/eu/timepit/refined/scodec/package.scala index accf68b6d..ef5fa0d28 100644 --- a/contrib/scodec/shared/src/main/scala/eu/timepit/refined/scodec/package.scala +++ b/contrib/scodec/shared/src/main/scala/eu/timepit/refined/scodec/package.scala @@ -2,27 +2,27 @@ package eu.timepit.refined import _root_.scodec._ import _root_.scodec.bits.BitVector -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.RefinedType package object scodec { - implicit def refTypeCodec[F[_, _], T, P]( + implicit def refTypeCodec[FTP, T]( implicit - codec: Codec[T], refType: RefType[F], validate: Validate[T, P] - ): Codec[F[T, P]] = - new Codec[F[T, P]] { + codec: Codec[T], rt: RefinedType.AuxT[FTP, T] + ): Codec[FTP] = + new Codec[FTP] { override def sizeBound: SizeBound = codec.sizeBound - override def decode(bits: BitVector): Attempt[DecodeResult[F[T, P]]] = + override def decode(bits: BitVector): Attempt[DecodeResult[FTP]] = codec.decode(bits).flatMap { t => - refType.refine[P](t.value) match { + rt.refine(t.value) match { case Right(tp) => Attempt.successful(DecodeResult(tp, t.remainder)) case Left(err) => Attempt.failure(Err(err)) } } - override def encode(value: F[T, P]): Attempt[BitVector] = - codec.encode(refType.unwrap(value)) + override def encode(value: FTP): Attempt[BitVector] = + codec.encode(rt.unwrap(value)) } } diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala index 09c248178..5bc1fe7f2 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala @@ -27,6 +27,9 @@ trait RefinedType[FTP] { implicit rt: RefinedType.AuxT[FTP, T] ): FTP = macro macros.RefineMacro.refineImpl[FTP, T, P] + + def unwrap(tp: FTP): T = + refType.unwrap(subst2(tp)) } object RefinedType { diff --git a/core/shared/src/test/scala/eu/timepit/refined/api/RefTypeSpec.scala b/core/shared/src/test/scala/eu/timepit/refined/api/RefTypeSpec.scala index dc99d9bb4..90e5916f2 100644 --- a/core/shared/src/test/scala/eu/timepit/refined/api/RefTypeSpec.scala +++ b/core/shared/src/test/scala/eu/timepit/refined/api/RefTypeSpec.scala @@ -126,7 +126,7 @@ class RefTypeSpecRefined extends RefTypeSpec[Refined]("Refined") { val y: Natural = 1L val z = 1L: Natural illTyped("Natural(-1L)", "Predicate.*fail.*") - illTyped("Natural(1.3)", "Cannot prove that.*") + illTyped("Natural(1.3)", "could not find implicit value.*") x == y && y == z } From 2ad47efc0dc15973d0ff98cdfe664cde8b4ce3ba Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Mon, 25 Jul 2016 19:56:02 +0200 Subject: [PATCH 09/16] Disable MiMa --- build.sbt | 2 +- .../main/scala/eu/timepit/refined/scalacheck/package.scala | 5 ++++- .../eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala | 4 ++-- .../eu/timepit/refined/scalacheck/StringArbitrarySpec.scala | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/build.sbt b/build.sbt index c83347b94..1a7334bf5 100644 --- a/build.sbt +++ b/build.sbt @@ -337,7 +337,7 @@ addCommandAlias("testJVM", allSubprojectsJVM map (_ + "/test") mkString (";", "; val validateCommands = List( "clean", - "mimaReportBinaryIssues", + //"mimaReportBinaryIssues", "coverageOff", "testJS", "coverage", diff --git a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala index bbf2fb2ed..94113e331 100644 --- a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala +++ b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala @@ -1,6 +1,6 @@ package eu.timepit.refined -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.{ RefinedType, RefType, Validate } import org.scalacheck.{ Arbitrary, Gen, Prop } package object scalacheck { @@ -10,4 +10,7 @@ package object scalacheck { def checkArbitraryRefType[F[_, _], T, P](implicit arb: Arbitrary[F[T, P]], rt: RefType[F], v: Validate[T, P]): Prop = Prop.forAll((tp: F[T, P]) => v.isValid(rt.unwrap(tp))) + + def checkArbitraryRefinedType[FTP](implicit arb: Arbitrary[FTP], rt: RefinedType[FTP]): Prop = + Prop.forAll((tp: FTP) => rt.validate.isValid(rt.unwrap(tp))) } diff --git a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala index b102492d6..84381b640 100644 --- a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala +++ b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala @@ -79,10 +79,10 @@ class NumericArbitrarySpec extends Properties("NumericArbitrary") { checkArbitraryRefType[Refined, Float, Interval.ClosedOpen[W.`0.4F`.T, W.`0.6F`.T]] property("Interval.Closed") = - checkArbitraryRefType[Refined, Int, Interval.Closed[W.`23`.T, W.`42`.T]] + checkArbitraryRefinedType[Int Refined Interval.Closed[W.`23`.T, W.`42`.T]] property("Interval.alias") = - forAll { m: Minute => m >= 0 && m <= 59 } + checkArbitraryRefinedType[Minute] property("chooseRefinedNum") = { type Natural = Int Refined NonNegative diff --git a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala index bbb4f91ca..986242406 100644 --- a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala +++ b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala @@ -11,7 +11,7 @@ import org.scalacheck.Properties class StringArbitrarySpec extends Properties("StringArbitrary") { property("EndsWith") = - checkArbitraryRefType[Refined, String, EndsWith[W.`"abc"`.T]] + checkArbitraryRefinedType[String Refined EndsWith[W.`"abc"`.T]] property("MatchesRegex") = checkArbitraryRefType[Refined, String, MatchesRegex[W.`".{2,}"`.T]] From ae5cad322820ebe475872e3b5728821362a3bade Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Mon, 25 Jul 2016 21:04:45 +0200 Subject: [PATCH 10/16] Use checkArbitraryRefinedType --- .../timepit/refined/scalacheck/package.scala | 1 + .../scalacheck/CharArbitrarySpec.scala | 14 +++--- .../scalacheck/GenericArbitrarySpec.scala | 2 +- .../scalacheck/NumericArbitrarySpec.scala | 44 +++++++++---------- .../scalacheck/StringArbitrarySpec.scala | 6 +-- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala index 94113e331..9f5998a8a 100644 --- a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala +++ b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala @@ -8,6 +8,7 @@ package object scalacheck { def arbitraryRefType[F[_, _], T, P](gen: Gen[T])(implicit rt: RefType[F]): Arbitrary[F[T, P]] = Arbitrary(gen.map(rt.unsafeWrap)) + @deprecated("", "") def checkArbitraryRefType[F[_, _], T, P](implicit arb: Arbitrary[F[T, P]], rt: RefType[F], v: Validate[T, P]): Prop = Prop.forAll((tp: F[T, P]) => v.isValid(rt.unwrap(tp))) diff --git a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CharArbitrarySpec.scala b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CharArbitrarySpec.scala index 081467d8c..153958bc8 100644 --- a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CharArbitrarySpec.scala +++ b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/CharArbitrarySpec.scala @@ -13,25 +13,25 @@ import org.scalacheck.Properties class CharArbitrarySpec extends Properties("CharArbitrarySpec") { property("Digit") = - checkArbitraryRefType[Refined, Char, Digit] + checkArbitraryRefinedType[Char Refined Digit] property("Letter") = - checkArbitraryRefType[Refined, Char, Letter] + checkArbitraryRefinedType[Char Refined Letter] property("LowerCase") = - checkArbitraryRefType[Refined, Char, LowerCase] + checkArbitraryRefinedType[Char Refined LowerCase] property("UpperCase") = - checkArbitraryRefType[Refined, Char, UpperCase] + checkArbitraryRefinedType[Char Refined UpperCase] property("Whitespace") = - checkArbitraryRefType[Refined, Char, Whitespace] + checkArbitraryRefinedType[Char Refined Whitespace] property("LetterOrDigit") = - checkArbitraryRefType[Refined, Char, LetterOrDigit] + checkArbitraryRefinedType[Char Refined LetterOrDigit] property("HexDigit") = { type HexDigit = Digit Or Interval.Closed[W.`'a'`.T, W.`'f'`.T] - checkArbitraryRefType[Refined, Char, HexDigit] + checkArbitraryRefinedType[Char Refined HexDigit] } } diff --git a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/GenericArbitrarySpec.scala b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/GenericArbitrarySpec.scala index 23959cb6a..d535560f6 100644 --- a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/GenericArbitrarySpec.scala +++ b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/GenericArbitrarySpec.scala @@ -9,5 +9,5 @@ import org.scalacheck.Properties class GenericArbitrarySpec extends Properties("GenericArbitrary") { property("Equal") = - checkArbitraryRefType[Refined, Int, Equal[W.`100`.T]] + checkArbitraryRefinedType[Int Refined Equal[W.`100`.T]] } diff --git a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala index 84381b640..826014df5 100644 --- a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala +++ b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/NumericArbitrarySpec.scala @@ -13,70 +13,70 @@ import shapeless.nat._ class NumericArbitrarySpec extends Properties("NumericArbitrary") { property("Less.positive") = - checkArbitraryRefType[Refined, Int, Less[W.`100`.T]] + checkArbitraryRefinedType[Int Refined Less[W.`100`.T]] property("Less.negative") = - checkArbitraryRefType[Refined, Int, Less[W.`-100`.T]] + checkArbitraryRefinedType[Int Refined Less[W.`-100`.T]] property("Less.Nat") = - checkArbitraryRefType[Refined, Long, Less[_10]] + checkArbitraryRefinedType[Long Refined Less[_10]] property("LessEqual.positive") = - checkArbitraryRefType[Refined, Int, LessEqual[W.`42`.T]] + checkArbitraryRefinedType[Int Refined LessEqual[W.`42`.T]] property("LessEqual.negative") = - checkArbitraryRefType[Refined, Int, LessEqual[W.`-42`.T]] + checkArbitraryRefinedType[Int Refined LessEqual[W.`-42`.T]] property("LessEqual.Nat") = - checkArbitraryRefType[Refined, Long, LessEqual[_10]] + checkArbitraryRefinedType[Long Refined LessEqual[_10]] property("Greater.positive") = - checkArbitraryRefType[Refined, Int, Greater[W.`100`.T]] + checkArbitraryRefinedType[Int Refined Greater[W.`100`.T]] property("Greater.negative") = - checkArbitraryRefType[Refined, Int, Greater[W.`-100`.T]] + checkArbitraryRefinedType[Int Refined Greater[W.`-100`.T]] property("Greater.Nat") = - checkArbitraryRefType[Refined, Long, Greater[_10]] + checkArbitraryRefinedType[Long Refined Greater[_10]] property("GreaterEqual.positive") = - checkArbitraryRefType[Refined, Int, GreaterEqual[W.`123456`.T]] + checkArbitraryRefinedType[Int Refined GreaterEqual[W.`123456`.T]] property("GreaterEqual.negative") = - checkArbitraryRefType[Refined, Int, GreaterEqual[W.`-123456`.T]] + checkArbitraryRefinedType[Int Refined GreaterEqual[W.`-123456`.T]] property("GreaterEqual.Nat") = - checkArbitraryRefType[Refined, Int, GreaterEqual[_10]] + checkArbitraryRefinedType[Int Refined GreaterEqual[_10]] property("Positive") = - checkArbitraryRefType[Refined, Float, Positive] + checkArbitraryRefinedType[Float Refined Positive] property("NonPositive") = - checkArbitraryRefType[Refined, Short, NonPositive] + checkArbitraryRefinedType[Short Refined NonPositive] property("Negative") = - checkArbitraryRefType[Refined, Double, Negative] + checkArbitraryRefinedType[Double Refined Negative] property("NonNegative") = - checkArbitraryRefType[Refined, Long, NonNegative] + checkArbitraryRefinedType[Long Refined NonNegative] property("Interval.Open") = - checkArbitraryRefType[Refined, Int, Interval.Open[W.`-23`.T, W.`42`.T]] + checkArbitraryRefinedType[Int Refined Interval.Open[W.`-23`.T, W.`42`.T]] property("Interval.Open (0.554, 0.556)") = - checkArbitraryRefType[Refined, Double, Interval.Open[W.`0.554`.T, W.`0.556`.T]] + checkArbitraryRefinedType[Double Refined Interval.Open[W.`0.554`.T, W.`0.556`.T]] property("Interval.OpenClosed") = - checkArbitraryRefType[Refined, Double, Interval.OpenClosed[W.`2.71828`.T, W.`3.14159`.T]] + checkArbitraryRefinedType[Double Refined Interval.OpenClosed[W.`2.71828`.T, W.`3.14159`.T]] property("Interval.OpenClosed (0.54, 0.56]") = - checkArbitraryRefType[Refined, Float, Interval.OpenClosed[W.`0.54F`.T, W.`0.56F`.T]] + checkArbitraryRefinedType[Float Refined Interval.OpenClosed[W.`0.54F`.T, W.`0.56F`.T]] property("Interval.ClosedOpen") = - checkArbitraryRefType[Refined, Double, Interval.ClosedOpen[W.`-2.71828`.T, W.`3.14159`.T]] + checkArbitraryRefinedType[Double Refined Interval.ClosedOpen[W.`-2.71828`.T, W.`3.14159`.T]] property("Interval.ClosedOpen [0.4, 0.6)") = - checkArbitraryRefType[Refined, Float, Interval.ClosedOpen[W.`0.4F`.T, W.`0.6F`.T]] + checkArbitraryRefinedType[Float Refined Interval.ClosedOpen[W.`0.4F`.T, W.`0.6F`.T]] property("Interval.Closed") = checkArbitraryRefinedType[Int Refined Interval.Closed[W.`23`.T, W.`42`.T]] diff --git a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala index 986242406..ab887c080 100644 --- a/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala +++ b/contrib/scalacheck/shared/src/test/scala/eu/timepit/refined/scalacheck/StringArbitrarySpec.scala @@ -14,13 +14,13 @@ class StringArbitrarySpec extends Properties("StringArbitrary") { checkArbitraryRefinedType[String Refined EndsWith[W.`"abc"`.T]] property("MatchesRegex") = - checkArbitraryRefType[Refined, String, MatchesRegex[W.`".{2,}"`.T]] + checkArbitraryRefinedType[String Refined MatchesRegex[W.`".{2,}"`.T]] property("StartsWith") = - checkArbitraryRefType[Refined, String, StartsWith[W.`"abc"`.T]] + checkArbitraryRefinedType[String Refined StartsWith[W.`"abc"`.T]] // collection predicates property("NonEmpty") = - checkArbitraryRefType[Refined, String, NonEmpty] + checkArbitraryRefinedType[String Refined NonEmpty] } From e7be749b243f9d95d0d584a948b933d3fe8b203b Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Mon, 25 Jul 2016 22:58:43 +0200 Subject: [PATCH 11/16] Implement refine macros in terms of refineImpl --- .../main/scala/eu/timepit/refined/auto.scala | 10 +++--- .../timepit/refined/macros/RefineMacro.scala | 36 +++++++------------ 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/core/shared/src/main/scala/eu/timepit/refined/auto.scala b/core/shared/src/main/scala/eu/timepit/refined/auto.scala index 9226c05d3..9b4f37eb3 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/auto.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/auto.scala @@ -1,6 +1,6 @@ package eu.timepit.refined -import eu.timepit.refined.api.{ Refined, RefType, Validate } +import eu.timepit.refined.api.{ Refined, RefinedType, RefType } import eu.timepit.refined.api.Inference.==> import eu.timepit.refined.macros.{ InferMacro, RefineMacro } import shapeless.tag.@@ @@ -52,8 +52,8 @@ object auto { */ implicit def autoRefineV[T, P](t: T)( implicit - rt: RefType[Refined], v: Validate[T, P] - ): Refined[T, P] = macro RefineMacro.impl[Refined, T, P] + rt: RefinedType.AuxT[Refined[T, P], T] + ): Refined[T, P] = macro RefineMacro.refineImpl[Refined[T, P], T, P] /** * Implicitly tags (at compile-time) a value of type `T` with `P` if `t` @@ -64,6 +64,6 @@ object auto { */ implicit def autoRefineT[T, P](t: T)( implicit - rt: RefType[@@], v: Validate[T, P] - ): T @@ P = macro RefineMacro.impl[@@, T, P] + rt: RefinedType.AuxT[T @@ P, T] + ): T @@ P = macro RefineMacro.refineImpl[T @@ P, T, P] } diff --git a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala index da33a77a7..d57497213 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala @@ -10,30 +10,6 @@ import scala.reflect.macros.blackbox class RefineMacro(val c: blackbox.Context) extends MacroUtils { import c.universe._ - def impl[F[_, _], T: c.WeakTypeTag, P: c.WeakTypeTag](t: c.Expr[T])( - rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] - ): c.Expr[F[T, P]] = { - - val tValue: T = t.tree match { - case Literal(Constant(value)) => value.asInstanceOf[T] - case _ => abort(Resources.refineNonCompileTimeConstant) - } - - val validate = eval(v) - val res = validate.validate(tValue) - if (res.isFailed) { - abort(validate.showResult(tValue, res)) - } - - val refType = eval(rt) - refType.unsafeWrapM(c)(t) - } - - def implApplyRef[FTP, F[_, _], T, P](t: c.Expr[T])( - ev: c.Expr[F[T, P] =:= FTP], rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] - ): c.Expr[FTP] = - c.Expr(impl(t)(rt, v).tree) - def refineImpl[FTP, T: c.WeakTypeTag, P: c.WeakTypeTag](t: c.Expr[T])( rt: c.Expr[api.RefinedType.AuxT[FTP, T]] ): c.Expr[FTP] = { @@ -50,4 +26,16 @@ class RefineMacro(val c: blackbox.Context) extends MacroUtils { c.Expr[FTP](refinedType.refType.unsafeWrapM[T, P](c)(t).tree) } + + @deprecated("", "") + def impl[F[_, _], T: c.WeakTypeTag, P: c.WeakTypeTag](t: c.Expr[T])( + rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] + ): c.Expr[F[T, P]] = + refineImpl(t)(reify(api.RefinedType.instance(rt.splice, v.splice))) + + @deprecated("", "") + def implApplyRef[FTP, F[_, _], T, P](t: c.Expr[T])( + ev: c.Expr[F[T, P] =:= FTP], rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] + ): c.Expr[FTP] = + c.Expr(impl(t)(rt, v).tree) } From 37396465f5958b9f9f7a915a7428f4b15eb4f53a Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 26 Jul 2016 05:13:24 +0200 Subject: [PATCH 12/16] Fix compile error on 2.10 --- .../src/main/scala/eu/timepit/refined/macros/RefineMacro.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala index d57497213..c5972d997 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala @@ -31,7 +31,7 @@ class RefineMacro(val c: blackbox.Context) extends MacroUtils { def impl[F[_, _], T: c.WeakTypeTag, P: c.WeakTypeTag](t: c.Expr[T])( rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] ): c.Expr[F[T, P]] = - refineImpl(t)(reify(api.RefinedType.instance(rt.splice, v.splice))) + refineImpl[F[T, P], T, P](t)(reify(api.RefinedType.instance(rt.splice, v.splice))) @deprecated("", "") def implApplyRef[FTP, F[_, _], T, P](t: c.Expr[T])( From a0160f773f5bdfce097d8600694791bf1a713433 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 26 Jul 2016 05:38:19 +0200 Subject: [PATCH 13/16] wip --- .../main/scala/eu/timepit/refined/scalacheck/package.scala | 2 +- .../main/scala/eu/timepit/refined/macros/RefineMacro.scala | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala index 9f5998a8a..34845582a 100644 --- a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala +++ b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/package.scala @@ -8,7 +8,7 @@ package object scalacheck { def arbitraryRefType[F[_, _], T, P](gen: Gen[T])(implicit rt: RefType[F]): Arbitrary[F[T, P]] = Arbitrary(gen.map(rt.unsafeWrap)) - @deprecated("", "") + @deprecated("", "0.6.0") def checkArbitraryRefType[F[_, _], T, P](implicit arb: Arbitrary[F[T, P]], rt: RefType[F], v: Validate[T, P]): Prop = Prop.forAll((tp: F[T, P]) => v.isValid(rt.unwrap(tp))) diff --git a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala index c5972d997..493039884 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/macros/RefineMacro.scala @@ -27,13 +27,13 @@ class RefineMacro(val c: blackbox.Context) extends MacroUtils { c.Expr[FTP](refinedType.refType.unsafeWrapM[T, P](c)(t).tree) } - @deprecated("", "") + @deprecated("", "0.6.0") def impl[F[_, _], T: c.WeakTypeTag, P: c.WeakTypeTag](t: c.Expr[T])( rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] ): c.Expr[F[T, P]] = refineImpl[F[T, P], T, P](t)(reify(api.RefinedType.instance(rt.splice, v.splice))) - @deprecated("", "") + @deprecated("", "0.6.0") def implApplyRef[FTP, F[_, _], T, P](t: c.Expr[T])( ev: c.Expr[F[T, P] =:= FTP], rt: c.Expr[RefType[F]], v: c.Expr[Validate[T, P]] ): c.Expr[FTP] = From 5faef9e7a1b76e0bd1db143443323174f654b096 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 26 Jul 2016 05:45:41 +0200 Subject: [PATCH 14/16] bump scalacheck version to fix scala.js build error --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 1a7334bf5..1854db052 100644 --- a/build.sbt +++ b/build.sbt @@ -26,7 +26,7 @@ val commonImports = s""" val macroCompatVersion = "1.1.1" val macroParadiseVersion = "2.1.0" val shapelessVersion = "2.3.1" -val scalaCheckVersion = "1.12.5" +val scalaCheckVersion = "1.13.2" val scalazVersion = "7.2.4" val scodecVersion = "1.10.2" From e79ee1d4fba6a7c48f66849788e02ed4f22b1324 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Tue, 26 Jul 2016 23:13:39 +0200 Subject: [PATCH 15/16] wip --- .../eu/timepit/refined/scalacheck/numeric.scala | 13 +++++++------ .../eu/timepit/refined/api/RefinedType.scala | 15 +++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala index 0e7bc0b8e..c4deb4fee 100644 --- a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala +++ b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala @@ -1,7 +1,7 @@ package eu.timepit.refined package scalacheck -import eu.timepit.refined.api.{ RefType, Validate } +import eu.timepit.refined.api.{ RefinedType, RefType } import eu.timepit.refined.numeric._ import eu.timepit.refined.scalacheck.util.{ Adjacent, Bounded } import org.scalacheck.{ Arbitrary, Gen } @@ -22,12 +22,13 @@ object numeric { * * This is like ScalaCheck's `Gen.chooseNum` but for refined types. */ - def chooseRefinedNum[F[_, _], T: Numeric: Choose, P](min: F[T, P], max: F[T, P])( + def chooseRefinedNum[FTP, T: Numeric: Choose](min: FTP, max: FTP)( implicit - rt: RefType[F], - v: Validate[T, P] - ): Gen[F[T, P]] = - Gen.chooseNum(rt.unwrap(min), rt.unwrap(max)).filter(v.isValid).map(rt.unsafeWrap) + rt: RefinedType.AuxT[FTP, T] + ): Gen[FTP] = + Gen.chooseNum(rt.unwrap(min), rt.unwrap(max)) + .filter(rt.validate.isValid) + .map(rt.wrapUnsafe) /// diff --git a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala index 5bc1fe7f2..6ed560fdf 100644 --- a/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala +++ b/core/shared/src/main/scala/eu/timepit/refined/api/RefinedType.scala @@ -10,13 +10,13 @@ trait RefinedType[FTP] { val validate: Validate[T, P] - val subst1: F[T, P] =:= FTP + val alias: F[T, P] =:= FTP - val subst2: FTP =:= F[T, P] + val unalias: FTP =:= F[T, P] def refine(t: T): Either[String, FTP] = { val res = validate.validate(t) - if (res.isPassed) Right(subst1(refType.unsafeWrap(t))) + if (res.isPassed) Right(wrapUnsafe(t)) else Left(validate.showResult(t, res)) } @@ -29,7 +29,10 @@ trait RefinedType[FTP] { ): FTP = macro macros.RefineMacro.refineImpl[FTP, T, P] def unwrap(tp: FTP): T = - refType.unwrap(subst2(tp)) + refType.unwrap(unalias(tp)) + + def wrapUnsafe(t: T): FTP = + alias(refType.unsafeWrap(t)) } object RefinedType { @@ -57,7 +60,7 @@ object RefinedType { override val refType: RefType[F] = rt override val validate: Validate[T, P] = v - override val subst1: F[T, P] =:= F0[T, P0] = implicitly - override val subst2: F0[T0, P0] =:= F[T, P] = implicitly + override val alias: F[T, P] =:= F0[T, P0] = implicitly + override val unalias: F0[T0, P0] =:= F[T, P] = implicitly } } From 7090c691768a7247ee210e3595b4beef996cd837 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Wed, 27 Jul 2016 22:46:12 +0200 Subject: [PATCH 16/16] fix --- .../main/scala/eu/timepit/refined/scalacheck/numeric.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala index c4deb4fee..b2e0b5f06 100644 --- a/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala +++ b/contrib/scalacheck/shared/src/main/scala/eu/timepit/refined/scalacheck/numeric.scala @@ -22,9 +22,9 @@ object numeric { * * This is like ScalaCheck's `Gen.chooseNum` but for refined types. */ - def chooseRefinedNum[FTP, T: Numeric: Choose](min: FTP, max: FTP)( + def chooseRefinedNum[FTP, T](min: FTP, max: FTP)( implicit - rt: RefinedType.AuxT[FTP, T] + rt: RefinedType.AuxT[FTP, T], nt: Numeric[T], ct: Choose[T] ): Gen[FTP] = Gen.chooseNum(rt.unwrap(min), rt.unwrap(max)) .filter(rt.validate.isValid)