Releases: kevin-lee/refined4s
v0.11.0
0.11.0 - 2024-01-04
New Feature
-
[
refined4s-core
] AddMinValue
andMaxValue
to refined basic numeric types (#223)- Add
Min
trait - Add
Max
trait - Add
MinMax
trait
Add
MinMax
to the following types to haveMinValue
andMaxValue
NegInt
NonNegInt
PosInt
NonPosInt
NegLong
NonNegLong
PosLong
NonPosLong
NegShort
NonNegShort
PosShort
NonPosShort
NegByte
NonNegByte
PosByte
NonPosByte
NegFloat
NonNegFloat
PosFloat
NonPosFloat
NegDouble
NonNegDouble
PosDouble
NonPosDouble
- Add
Internal Change
- [
refined4s-core
] MoveNumeric
andInlinedNumeric
fromnumeric
trait tonumeric
object (#225)
v0.10.0
0.10.0 - 2024-01-02
New Feature
- Release
refined4s-extras-render
module (#220) - Add
refined4s-extras-render
to supportRender
forrefined4s
(#215)e.g.)refined4s.modules.extras.derivation.ExtrasRender refined4s.modules.extras.derivation.types.all.given refined4s.modules.extras.derivation.generic.auto.given
import extras.render.Render import refined4s.types.all.* import refined4s.modules.extras.derivation.types.all.given val name = NonEmptyString("Kevin") Render[NonEmptyString].render(name) // String = Kevin
import extras.render.Render import refined4s.Newtype import refined4s.modules.extras.derivation.ExtrasRender type Name = Name.Type object Name extends Newtype[String], ExtrasRender[String] val name = Name("Kevin") Render[Name].render(name) // String = Kevin
import extras.render.Render import refined4s.Newtype type Name = Name.Type object Name extends Newtype[String] import refined4s.modules.extras.derivation.generic.auto.given val name = Name("Kevin") Render[Name].render(name) // String = Kevin
v0.9.0
0.9.0 - 2024-01-02
NOTE:
refined4s-extras-render
was not released by mistake, and it will be released inv0.10.0
.
New Feature
- Add
refined4s-extras-render
to supportRender
forrefined4s
(#215)e.g.)refined4s.modules.extras.derivation.ExtrasRender refined4s.modules.extras.derivation.types.all.given refined4s.modules.extras.derivation.generic.auto.given
import extras.render.Render import refined4s.types.all.* import refined4s.modules.extras.derivation.types.all.given val name = NonEmptyString("Kevin") Render[NonEmptyString].render(name) // String = Kevin
import extras.render.Render import refined4s.Newtype import refined4s.modules.extras.derivation.ExtrasRender type Name = Name.Type object Name extends Newtype[String], ExtrasRender[String] val name = Name("Kevin") Render[Name].render(name) // String = Kevin
import extras.render.Render import refined4s.Newtype type Name = Name.Type object Name extends Newtype[String] import refined4s.modules.extras.derivation.generic.auto.given val name = Name("Kevin") Render[Name].render(name) // String = Kevin
v0.8.0
v0.7.0
0.7.0 - 2023-12-30
Changes
- [
refined4s-cats
] RenamevalidateAs
inrefined4s.modules.cats.syntax
torefinedNewtypeNec
(#182)
-
[
refined4s-core
] MovetoValue
fromrefined4s.syntax
torefined4s.NewtypeBase
(#186)So with the given following code,
import refined4s.* import refined4s.types.all.* type Name = Name.Type object Name extends Newtype[NonEmptyString]
the following is possible without importing any
syntax
.val name = Name(NonEmptyString("Kevin")) name.toValue // String = "Kevin"
New Features
-
[
refined4s-cats
] AddrefinedNewtypeNel
inrefined4s.modules.cats.syntax
(#184)import refined4s.* import refined4s.types.all.* import refined4s.modules.cats.syntax.* type Name = Name.Type object Name extends Newtype[NonEmptyString] "Kevin".refinedNewtypeNel[Name] // EitherNel[String, Name] = Right(Name(NonEmptyString("Kevin"))) "".refinedNewtypeNel[Name] // EitherNel[String, Name] = Left(NonEmptyList("Failed to create Name: Invalid value: []. It has to be a non-empty String but got \"\"))
-
[
refined4s-cats
] AddvalidateAs
inrefined4s.modules.cats.syntax
to validate a value and returnValidated
(#188)import refined4s.* import refined4s.types.all.* import refined4s.modules.cats.syntax.* type Name = Name.Type object Name extends Newtype[NonEmptyString] "Kevin".validateAs[Name] // Validated[String, Name] = Valid(Name(NonEmptyString("Kevin"))) "".validateAs[Name] // Validated[String, Name] = Invalid("Failed to create Name: Invalid value: []. It has to be a non-empty String but got \"\")
-
[
refined4s-cats
] AddvalidateNecAs
inrefined4s.modules.cats.syntax
to validate a value and returnValidatedNec
(#189)import refined4s.* import refined4s.types.all.* import refined4s.modules.cats.syntax.* type Name = Name.Type object Name extends Newtype[NonEmptyString] "Kevin".validateNecAs[Name] // ValidatedNec[String, Name] = Valid(Name(NonEmptyString("Kevin"))) "".validateNecAs[Name] // ValidatedNec[String, Name] = Invalid(NonEmptyChain("Failed to create Name: Invalid value: []. It has to be a non-empty String but got \"\"))
-
[
refined4s-cats
] AddvalidateNelAs
inrefined4s.modules.cats.syntax
to validate a value and returnValidatedNel
(#190)import refined4s.* import refined4s.types.all.* import refined4s.modules.cats.syntax.* type Name = Name.Type object Name extends Newtype[NonEmptyString] "Kevin".validateNelAs[Name] // ValidatedNel[String, Name] = Valid(Name(NonEmptyString("Kevin"))) "".validateNelAs[Name] // ValidatedNel[String, Name] = Invalid(NonEmptyList("Failed to create Name: Invalid value: []. It has to be a non-empty String but got \"\"))
-
[
refined4s-cats
] AddderivedOrder
to have the instance ofOrder[A]
derived fromCoercible[A, B]
andOrder[B]
(#194)Given
import refined4s.* type MyNum = MyNum.Type object MyNum extends Newtype[Int]
it can be
import cats.* val n1 = MyNum(1) val n2 = MyNum(2) Order[MyNum].compare(n1, n2) // Int = -1
-
[
refined4s-core
] AddCanBeOrdered
for providingOrdering
andConversion[Type, Ordered[Type]]
(#196)import refined4s.* type MyNum = MyNum.Type object MyNum extends Newtype[Int]
val input1 = MyNum(1) val input2 = MyNum(2) Ordering[MyNum].compare(input1, input2) // Int = -1 (input1: Ordered[MyNum]).compare(input2) // Int = -1
- [
refined4s-core
] MakeNonEmptyString
CanBeOrdered
to haveOrdering[NonEmptyString]
andConversion[NonEmptyString, Ordered[NonEmptyString]]
(#198)
- [
refined4s-cats
] AddCatsOrder
(#203)import refined4s.* type MyNum = MyNum.Type object MyNum extends Newtype[Int], CatsOrder[Int]
import cats.* val myNum1 = NyNum(1) val myNum2 = NyNum(2) Order[MyNum].compare(myNum1, myNum1) // Int = 0 Order[MyNum].compare(myNum1, myNum2) // Int = -1 Order[MyNum].compare(myNum2, myNum1) // Int = 1
Internal Changes
- [
refined4s-core
] ReplaceOrdering
andConversion[Type, Ordered[Type]]
for numeric types withCanBeOrdered
(#199)
v0.6.0
0.6.0 - 2023-12-28
Changes
- All modules: importing
derivation.instances.given
can cause an issue as it overrides all type-classes defined in the companion objects (#163)-
[
refined4s-cats
] Add explicitEq
andShow
for pre-defined types (#171)- Now it has
refined4s.modules.cats.derivation.types.all
for the all pre-defined types (e.g.NegInt
,PosInt
,NonEmptyString
, etc.) refined4s.modules.cats.derivation.instances
=>refined4s.modules.cats.derivation.generic.auto
refined4s.modules.cats.derivation.instances.contraCoercible
is moved torefined4s.modules.cats.syntax
- Now it has
-
[
refined4s-circe
] Add explicitEncoder
andDecoder
for pre-defined types (#166) -
[
refined4s-pureconfig
] Add explicitConfigReader
andConfigWriter
for pre-defined types (#172) -
[
refined4s-doobie
] Add explicitGet
andPut
for pre-defined types (#173)
-
-
[
refined4s-core
] Keep onlyall
object
for pre-defined types and remove all the others (#168)So this will be the only
import
available for using pre-defined typesimport refined4s.types.all.*
The following ones have been removed.
import refined4s.types.numeric.* import refined4s.types.strings.* import refined4s.types.network.*
- Rename derived type classes - some of them have a naming conflict issue (#165)
v0.5.0
0.5.0 - 2023-12-23
New Features
-
[
refined4s-cats
] AddcontraCoercible
toF[B] => F[A]
withContravariant[F]
andCoercible[A, B]
(#152)This is useful to derive type-class instances for
Newtype
,Refined
andInlinedRefined
from the type-class instances of the actual types.e.g.)
import refined4s.modules.cats.derivation.instances.contraCoercible inline given eqDerived[A, B](using coercible: Coercible[A, B], eqB: Eq[B]): Eq[A] = contraCoercible(eqB) inline given showDerived[A, B](using coercible: Coercible[A, B], showB: Show[B]): Show[A] = contraCoercible(showB)
where
B
is the actual type andA
could be a newtype or a refined type.
Improvement
- Add missing
inline
toinvalidReason
in the sub-types ofInlinedNumeric
(#146)
-
[
refined4s-pureconfig
] Add type name to the error message ofPureconfigRefinedConfigReader
andrefined4s.modules.pureconfig.derivation.instances.derivedRefinedConfigReader
(#150)So a message like this
Invalid value found: -2373683071661092303 with error: Invalid value: [-2373683071661092303]. It must be a positive Long
should be like this instead.
The value -2373683071661092303 cannot be created as the expected type, mytypes.blah.Id.Type, due to the following error: Invalid value: [-2373683071661092303]. It must be a positive Long
- [
refined4s-doobie
] Make type-classes inrefined4s.modules.doobie.derivation.instances
inline
(#156)
-
[
refined4s-core
] Improve compile-time error message forinline apply
method (#158)The old compile-time error for the constant value passed to the
inline
apply
method may look like this.[error] 2780 | NegBigInt(1) [error] | ^^^^^^^^^^^^ [error] |A literal string is expected as an argument to `compiletime.error`. Got "Invalid value: [BigInt.apply(1)]. ".+( [error] | { [error] | val a$proxy4: BigInt = BigInt.apply(1) [error] | "It must be a negative BigInt":String:String [error] | }:String [error] |) [error] one error found
It is not so readable, and it is hard to comprehend what is wrong with the input.
After this release, it will be like
[error] 2780 | NegBigInt(1) [error] | ^^^^^^^^^^^^ [error] | Invalid value: [BigInt.apply(1)]. It must be a negative BigInt [error] one error found
Internal Housekeeping
-
[
refined4s-circe
] Updaterefined4s.modules.circe.derivation.instances.derivedEncoder
to usecontraCoercible
and make itinline
(#154)The old code has the following issue if it's turned into an
inline
method.[error] 13 | a => encoder(coercible(a)) [error] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ [error] |An inline given alias with a function value as right-hand side can significantly increase [error] |generated code size. You should either drop the `inline` or rewrite the given with an [error] |explicit `apply` method.
- Rename
Coercible
methods and type parameters (#160)wrap
andunwrap
suffixed withM
:M
toTC
(type constructor)wrap
andunwrap
suffixed withMOfM
:MOfM
toHKT
(higher-kinded type)M[*]
toF[*]
M1[*]
toF[*]
andM2[*]
toG[*]
e.g.)M1[M2[A]]
toF[G[A]]
v0.4.0
0.4.0 - 2023-12-16
New Features
- Add
refined4s-doobie-ce2
andrefined4s-doobie-ce3
modules to support doobie (#123) - [
refined4s-doobie
] AddGet
s andPut
forNewtype
,Refined
andInlinedRefined
withCoercible
andRefinedCtor
(#124) - [
refined4s-doobie
] AddDoobiePut
,DoobieNewtypeGet
,DoobieRefinedGet
,DoobieNewtypeGetPut
andDoobieRefinedGetPut
to have circeGet
andPut
derived from the actual type forNewtype
,Refined
andInlinedRefined
(#127)
v0.3.0
0.3.0 - 2023-12-15
Changes
- [
refined4s-cats
] ReplaceEq
andShow
instances for the existing refined types with the ones derived from the actual types usingCoercible
(#107)
New Features
-
[
refined4s-circe
] AddEncoder
andDecoder
s forNewtype
,Refined
andInlinedRefined
withCoercible
andRefinedCtor
(#103) -
[
refined4s-circe
] AddCirceEncoder
,CirceNewtypeDecoder
,CirceRefinedDecoder
,CirceNewtypeCodec
andCirceRefinedCodec
to have circeEncoder
andDecoder
derived from the actual type forNewtype
,Refined
andInlinedRefined
(#104)import refined4s.modules.circe.derivation.*
type MyNewtype = MyNewtype.Type object MyNewtype extends Newtype[String] with CirceEncoder[String] type MyRefinedType = MyRefinedType.Type object MyRefinedType extends Refined[String] with CirceEncoder[String] { override inline def invalidReason(a: String): String = "It has to be a non-empty String but got \"" + a + "\"" override inline def predicate(a: String): Boolean = a != "" } type MyRefinedNewtype = MyRefinedNewtype.Type object MyRefinedNewtype extends Newtype[MyRefinedType] with CirceEncoder[MyRefinedType]
type MyNewtype = MyNewtype.Type object MyNewtype extends Newtype[String] with CirceNewtypeDecoder[String] type MyRefinedType = MyRefinedType.Type object MyRefinedType extends Refined[String] with CirceRefinedDecoder[String] { override inline def invalidReason(a: String): String = "It has to be a non-empty String but got \"" + a + "\"" override inline def predicate(a: String): Boolean = a != "" } type MyRefinedNewtype = MyRefinedNewtype.Type object MyRefinedNewtype extends Newtype[MyRefinedType] with CirceNewtypeDecoder[MyRefinedType]
-
[
refined4s-core
] AddPortNumber
,SystemPortNumber
,NonSystemPortNumber
,UserPortNumber
andDynamicPortNumber
(#110) -
Add
refined4s-pureconfig
module to supportpureconfig
(#112) -
[
refined4s-pureconfig
] AddConfigReader
andConfigWriter
s forNewtype
,Refined
andInlinedRefined
withCoercible
andRefinedCtor
(#113)import refined4s.modules.pureconfig.derivation.instances.given
-
[
refined4s-pureconfig
] AddPureconfigNewtypeConfigReader
andPureconfigRefinedConfigReader
to providerConfigReader
forNewtype
,Refined
andInlinedRefined
(#116)type MyNewtype = MyNewtype.Type object MyNewtype extends Newtype[String] with PureconfigNewtypeConfigReader[String] type MyRefinedType = MyRefinedType.Type object MyRefinedType extends Refined[String] with PureconfigRefinedConfigReader[String] { override inline def invalidReason(a: String): String = "It has to be a non-empty String but got \"" + a + "\"" override inline def predicate(a: String): Boolean = a != "" } type MyRefinedNewtype = MyRefinedNewtype.Type object MyRefinedNewtype extends Newtype[MyRefinedType] with PureconfigNewtypeConfigReader[MyRefinedType] type MyInlinedRefinedType = MyInlinedRefinedType.Type object MyInlinedRefinedType extends InlinedRefined[String] with PureconfigRefinedConfigReader[String] { override inline def invalidReason(a: String): String = "It has to be a non-empty String but got \"" + a + "\"" override inline def predicate(a: String): Boolean = a != "" override inline def inlinedPredicate(inline a: String): Boolean = a != "" } type MyInlinedRefinedNewtype = MyInlinedRefinedNewtype.Type object MyInlinedRefinedNewtype extends Newtype[MyRefinedType] with PureconfigNewtypeConfigReader[MyRefinedType]
-
[
refined4s-pureconfig
] AddPureconfigConfigWriter
to providerConfigWriter
forNewtype
,Refined
andInlinedRefined
(#118)
v0.2.0
0.2.0 - 2023-12-10
Changes
- Rename
refined4s.cats
torefined4s.modules.cats
(#94)import refined4s.modules.cats.derivation.* import refined4s.modules.cats.syntax.*
New Features
-
Add
Eq[A]
andShow[A]
instances for the existing refined types (#95)So with
import refined4s.modules.cats.derivation.instances.given
Eq
andShow
instances for the following types are availableNegInt
NonNegInt
PosInt
NonPosInt
NegLong
NonNegLong
PosLong
NonPosLong
NegShort
NonNegShort
PosShort
NonPosShort
NegByte
NonNegByte
PosByte
NonPosByte
NegFloat
NonNegFloat
PosFloat
NonPosFloat
NegDouble
NonNegDouble
PosDouble
NonPosDouble
NegBigInt
NonNegBigInt
PosBigInt
NonPosBigInt
NegBigDecimal
NonNegBigDecimal
PosBigDecimal
NonPosBigDecimal
NonEmptyString
Uri