From 060886ea9b48e8e722785e645c873918530fd56d Mon Sep 17 00:00:00 2001 From: Ondra Pelech Date: Wed, 2 Oct 2024 13:01:57 +0200 Subject: [PATCH 1/2] Generalize HasBuilder to enable modelling infallible constructors (for NewtypeWrapped in contrast to NewValidated) --- .../shared/src/main/scala/monix/newtypes/HasBuilder.scala | 8 ++++---- .../src/main/scala/monix/newtypes/NewValidated.scala | 4 ++-- .../shared/src/main/scala/monix/newtypes/NewWrapped.scala | 4 ++-- core/shared/src/main/scala/monix/newtypes/Newtype.scala | 4 ++-- .../monix/newtypes/integrations/DerivedCirceCodec.scala | 4 ++-- .../newtypes/integrations/NewtypeKCirceCodecSuite.scala | 8 ++++---- .../newtypes/integrations/DerivedPureConfigConvert.scala | 2 +- .../newtypes/integrations/NewtypeKCirceCodecSuite.scala | 8 ++++---- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/core/shared/src/main/scala/monix/newtypes/HasBuilder.scala b/core/shared/src/main/scala/monix/newtypes/HasBuilder.scala index 3cad01c..510ca1e 100644 --- a/core/shared/src/main/scala/monix/newtypes/HasBuilder.scala +++ b/core/shared/src/main/scala/monix/newtypes/HasBuilder.scala @@ -25,16 +25,16 @@ package monix.newtypes * * @see [[HasExtractor]] for deriving encoders. */ -trait HasBuilder[Type] { +trait HasBuilder[Type, +Failure <: BuildFailure[Type]] { type Source - def build(value: Source): Either[BuildFailure[Type], Type] + def build(value: Source): Either[Failure, Type] } object HasBuilder { - type Aux[T, S] = HasBuilder[T] { type Source = S } + type Aux[T, +F <: BuildFailure[T], S] = HasBuilder[T, F] { type Source = S } - def apply[T](implicit ev: HasBuilder[T]): ev.type = ev + def apply[T, F <: BuildFailure[T]](implicit ev: HasBuilder[T, F]): ev.type = ev } /** diff --git a/core/shared/src/main/scala/monix/newtypes/NewValidated.scala b/core/shared/src/main/scala/monix/newtypes/NewValidated.scala index c1bb598..5db33e4 100644 --- a/core/shared/src/main/scala/monix/newtypes/NewValidated.scala +++ b/core/shared/src/main/scala/monix/newtypes/NewValidated.scala @@ -65,8 +65,8 @@ private[newtypes] trait NewValidated[Src] { self: NewEncoding[Src] => final def unapply[A](a: A)(implicit ev: A =:= Type): Some[Src] = Some(ev(a).value) - implicit final val builder: HasBuilder.Aux[Type, Src] = - new HasBuilder[Type] { + implicit final val builder: HasBuilder.Aux[Type, BuildFailure[Type], Src] = + new HasBuilder[Type, BuildFailure[Type]] { type Source = Src def build(value: Src): Either[BuildFailure[Type], Type] = apply(value) } diff --git a/core/shared/src/main/scala/monix/newtypes/NewWrapped.scala b/core/shared/src/main/scala/monix/newtypes/NewWrapped.scala index d8cca5b..d147d8e 100644 --- a/core/shared/src/main/scala/monix/newtypes/NewWrapped.scala +++ b/core/shared/src/main/scala/monix/newtypes/NewWrapped.scala @@ -73,8 +73,8 @@ private[newtypes] trait NewWrapped[Src] { self: NewEncoding[Src] => final def unapply[A](a: A)(implicit ev: A =:= Type): Some[Src] = Some(value(ev(a))) - implicit final val builder: HasBuilder.Aux[Type, Src] = - new HasBuilder[Type] { + implicit final val builder: HasBuilder.Aux[Type, Nothing, Src] = + new HasBuilder[Type, Nothing] { type Source = Src def build(value: Src) = Right(apply(value)) } diff --git a/core/shared/src/main/scala/monix/newtypes/Newtype.scala b/core/shared/src/main/scala/monix/newtypes/Newtype.scala index 1107c94..c0ba556 100644 --- a/core/shared/src/main/scala/monix/newtypes/Newtype.scala +++ b/core/shared/src/main/scala/monix/newtypes/Newtype.scala @@ -35,8 +35,8 @@ package monix.newtypes * * // Recommended instance, but not required; * // use Newtype.Validated to get rid of this boilerplate ;-) - * implicit val builder: HasBuilder.Aux[EmailAddress, String] = - * new HasBuilder[EmailAddress] { + * implicit val builder: HasBuilder.Aux[EmailAddress, String, BuildFailure[Type]] = + * new HasBuilder[EmailAddress, BuildFailure[Type]] { * type Source = String * * def build(v: String): Either[BuildFailure[Type], Type] = diff --git a/integration-circe/all/shared/src/main/scala/monix/newtypes/integrations/DerivedCirceCodec.scala b/integration-circe/all/shared/src/main/scala/monix/newtypes/integrations/DerivedCirceCodec.scala index 8674d57..fcbcc80 100644 --- a/integration-circe/all/shared/src/main/scala/monix/newtypes/integrations/DerivedCirceCodec.scala +++ b/integration-circe/all/shared/src/main/scala/monix/newtypes/integrations/DerivedCirceCodec.scala @@ -43,14 +43,14 @@ trait DerivedCirceCodec extends DerivedCirceEncoder with DerivedCirceDecoder */ trait DerivedCirceDecoder { implicit def jsonDecoder[T, S](implicit - builder: HasBuilder.Aux[T, S], + builder: HasBuilder.Aux[T, BuildFailure[T], S], dec: Decoder[S], ): Decoder[T] = { jsonDecode(_) } protected def jsonDecode[T, S](c: HCursor)(implicit - builder: HasBuilder.Aux[T, S], + builder: HasBuilder.Aux[T, BuildFailure[T], S], dec: Decoder[S], ): Decoder.Result[T] = dec.apply(c).flatMap { value => diff --git a/integration-circe/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala b/integration-circe/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala index f70d2f3..422d678 100644 --- a/integration-circe/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala +++ b/integration-circe/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala @@ -82,8 +82,8 @@ object NewtypeKCirceCodecSuite { def apply[A](first: A, rest: List[A]): Type[A] = unsafeCoerce(first :: rest) - implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], List[A]] = - new HasBuilder[Type[A]] { + implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], BuildFailure[Type[A]], List[A]] = + new HasBuilder[Type[A], BuildFailure[Type[A]]] { type Source = List[A] override def build(value: List[A]): Either[BuildFailure[Type[A]], Type[A]] = @@ -105,8 +105,8 @@ object NewtypeKCirceCodecSuite { def apply[A](first: A, rest: List[A]): Type[A] = unsafeCoerce(first :: rest) - implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], List[A]] = - new HasBuilder[Type[A]] { + implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], BuildFailure[Type[A]], List[A]] = + new HasBuilder[Type[A], BuildFailure[Type[A]]] { type Source = List[A] override def build(value: List[A]): Either[BuildFailure[Type[A]], Type[A]] = diff --git a/integration-pureconfig/all/shared/src/main/scala/monix/newtypes/integrations/DerivedPureConfigConvert.scala b/integration-pureconfig/all/shared/src/main/scala/monix/newtypes/integrations/DerivedPureConfigConvert.scala index 56e4ec1..6039004 100644 --- a/integration-pureconfig/all/shared/src/main/scala/monix/newtypes/integrations/DerivedPureConfigConvert.scala +++ b/integration-pureconfig/all/shared/src/main/scala/monix/newtypes/integrations/DerivedPureConfigConvert.scala @@ -39,7 +39,7 @@ trait DerivedPureConfigConvert extends DerivedPureConfigReader with DerivedPureC */ trait DerivedPureConfigReader { implicit def pureConfigReader[T, S](implicit - builder: HasBuilder.Aux[T, S], + builder: HasBuilder.Aux[T, BuildFailure[T], S], reader: ConfigReader[S], ): ConfigReader[T] = { reader.emap { value => diff --git a/integration-pureconfig/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala b/integration-pureconfig/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala index 64015fd..4abe080 100644 --- a/integration-pureconfig/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala +++ b/integration-pureconfig/all/shared/src/test/scala/monix/newtypes/integrations/NewtypeKCirceCodecSuite.scala @@ -47,8 +47,8 @@ object NewtypeKCirceCodecSuite { def apply[A](first: A, rest: List[A]): Type[A] = unsafeCoerce(first :: rest) - implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], List[A]] = - new HasBuilder[Type[A]] { + implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], BuildFailure[Type[A]], List[A]] = + new HasBuilder[Type[A], BuildFailure[Type[A]]] { type Source = List[A] override def build(value: List[A]): Either[BuildFailure[Type[A]], Type[A]] = @@ -65,8 +65,8 @@ object NewtypeKCirceCodecSuite { def apply[A](first: A, rest: List[A]): Type[A] = unsafeCoerce(first :: rest) - implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], List[A]] = - new HasBuilder[Type[A]] { + implicit final def builder[A: TypeInfo]: HasBuilder.Aux[Type[A], BuildFailure[Type[A]], List[A]] = + new HasBuilder[Type[A], BuildFailure[Type[A]]] { type Source = List[A] override def build(value: List[A]): Either[BuildFailure[Type[A]], Type[A]] = From d85707dfecf49e745be10759b1b5181348e5e9c5 Mon Sep 17 00:00:00 2001 From: Ondra Pelech Date: Fri, 4 Oct 2024 19:30:38 +0200 Subject: [PATCH 2/2] fix --- site/src/mdoc/docs/core.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/mdoc/docs/core.md b/site/src/mdoc/docs/core.md index df470cb..e070d73 100644 --- a/site/src/mdoc/docs/core.md +++ b/site/src/mdoc/docs/core.md @@ -344,7 +344,7 @@ included): ```scala mdoc:silent implicit def jsonDecoder[T, S](implicit - builder: HasBuilder.Aux[T, S], + builder: HasBuilder.Aux[T, BuildFailure[T], S], dec: Decoder[S], ): Decoder[T] = (c: HCursor) => { dec.apply(c).flatMap { value =>