diff --git a/core/src/main/scala/newtypes.scala b/core/src/main/scala/newtypes.scala index 934df33..4381511 100644 --- a/core/src/main/scala/newtypes.scala +++ b/core/src/main/scala/newtypes.scala @@ -23,34 +23,34 @@ object newtypes: type IntRuntime[A] = SameRuntime[A, Int] type DoubleRuntime[A] = SameRuntime[A, Double] - trait TotalWrapper[Newtype, Impl](using ev: Newtype =:= Impl): - inline def raw(inline a: Newtype): Impl = a - inline def apply(inline s: Impl): Newtype = s.asInstanceOf[Newtype] - inline def from[M[_]](inline f: M[Impl]): M[Newtype] = f.asInstanceOf[M[Newtype]] - inline def from[M[_], B](using sr: SameRuntime[B, Impl])(inline f: M[B]): M[Newtype] = + class TotalWrapper[Newtype, Impl](using Newtype =:= Impl): + inline final def raw(inline a: Newtype): Impl = a.asInstanceOf[Impl] + inline final def apply(inline s: Impl): Newtype = s.asInstanceOf[Newtype] + inline final def from[M[_]](inline f: M[Impl]): M[Newtype] = f.asInstanceOf[M[Newtype]] + inline final def from[M[_], B](using sr: SameRuntime[B, Impl])(inline f: M[B]): M[Newtype] = f.asInstanceOf[M[Newtype]] - inline def from[M[_], B](inline other: TotalWrapper[B, Impl])(inline f: M[B]): M[Newtype] = + inline final def from[M[_], B](inline other: TotalWrapper[B, Impl])(inline f: M[B]): M[Newtype] = f.asInstanceOf[M[Newtype]] - inline def raw[M[_]](inline f: M[Newtype]): M[Impl] = f.asInstanceOf[M[Impl]] + inline final def raw[M[_]](inline f: M[Newtype]): M[Impl] = f.asInstanceOf[M[Impl]] - given SameRuntime[Newtype, Impl] = identity + given SameRuntime[Newtype, Impl] = _.asInstanceOf[Impl] given SameRuntime[Impl, Newtype] = _.asInstanceOf[Newtype] given (using Eq[Impl]): Eq[Newtype] = Eq.by(_.value) extension (a: Newtype) - inline def value: Impl = a - inline def into[X](inline other: TotalWrapper[X, Impl]): X = other.apply(a) - inline def map(inline f: Impl => Impl): Newtype = apply(f(a)) + inline def value: Impl = a.asInstanceOf[Impl] + inline def into[X](inline other: TotalWrapper[X, Impl]): X = other.apply(a.asInstanceOf[Impl]) + inline def map(inline f: Impl => Impl): Newtype = apply(f(a.asInstanceOf[Impl])) end TotalWrapper - trait FunctionWrapper[Newtype, Impl](using ev: Newtype =:= Impl) extends TotalWrapper[Newtype, Impl]: - extension (a: Newtype) inline def apply: Impl = a + class FunctionWrapper[Newtype, Impl](using Newtype =:= Impl) extends TotalWrapper[Newtype, Impl]: + extension (a: Newtype) inline def apply: Impl = a.asInstanceOf[Impl] - trait OpaqueString[A](using A =:= String) extends TotalWrapper[A, String]: + class OpaqueString[A](using A =:= String) extends TotalWrapper[A, String]: given Show[A] = _.value given Render[A] = _.value - trait OpaqueInt[A](using A =:= Int) extends TotalWrapper[A, Int]: + class OpaqueInt[A](using A =:= Int) extends TotalWrapper[A, Int]: extension (inline a: A) inline def unary_- = apply(-raw(a)) inline infix def >(inline o: Int): Boolean = raw(a) > o @@ -59,8 +59,8 @@ object newtypes: inline infix def <=(inline o: Int): Boolean = raw(a) <= o inline infix def +(inline o: Int): A = apply(raw(a) + o) inline infix def -(inline o: Int): A = apply(raw(a) - o) - inline def atLeast(inline bot: Int): A = apply(math.max(raw(a), bot)) - inline def atMost(inline top: Int): A = apply(math.min(raw(a), top)) + inline def atLeast(inline bot: Int): A = apply(Math.max(raw(a), bot)) + inline def atMost(inline top: Int): A = apply(Math.min(raw(a), top)) inline infix def >(inline o: A): Boolean = >(raw(o)) inline infix def <(inline o: A): Boolean = <(raw(o)) inline infix def >=(inline o: A): Boolean = >=(raw(o)) @@ -70,13 +70,25 @@ object newtypes: inline def atLeast(inline bot: A): A = atLeast(raw(bot)) inline def atMost(inline top: A): A = atMost(raw(top)) - trait OpaqueLong[A](using A =:= Long) extends TotalWrapper[A, Long] - trait OpaqueDouble[A](using A =:= Double) extends TotalWrapper[A, Double]: + class OpaqueIntSafer[A](using A =:= Int) extends TotalWrapper[A, Int]: + extension (inline a: A) + inline def unary_- = apply(-raw(a)) + inline infix def >(inline o: A): Boolean = raw(a) > raw(o) + inline infix def <(inline o: A): Boolean = raw(a) < raw(o) + inline infix def >=(inline o: A): Boolean = raw(a) >= raw(o) + inline infix def <=(inline o: A): Boolean = raw(a) <= raw(o) + inline infix def +(inline o: A): A = apply(raw(a) + raw(o)) + inline infix def -(inline o: A): A = apply(raw(a) - raw(o)) + inline def atLeast(inline bot: A): A = apply(Math.max(raw(a), raw(bot))) + inline def atMost(inline top: A): A = apply(Math.min(raw(a), raw(top))) + + class OpaqueLong[A](using A =:= Long) extends TotalWrapper[A, Long] + class OpaqueDouble[A](using A =:= Double) extends TotalWrapper[A, Double]: extension (inline a: A) inline def +(inline o: Int): A = apply(raw(a) + o) - trait OpaqueFloat[A](using A =:= Float) extends TotalWrapper[A, Float] + class OpaqueFloat[A](using A =:= Float) extends TotalWrapper[A, Float] import scala.concurrent.duration.FiniteDuration - trait OpaqueDuration[A](using A =:= FiniteDuration) extends TotalWrapper[A, FiniteDuration] + class OpaqueDuration[A](using A =:= FiniteDuration) extends TotalWrapper[A, FiniteDuration] abstract class YesNo[A](using ev: Boolean =:= A): val Yes: A = true