v2.3.0
Introduction
This release brings ergonomic improvements for new types and other minor additions.
Main changes
Improved new types
Refactoring
RefinedTypeOps
has been refactored to be compatible with the future versions of Scala. RefinedTypeOps[T]
is now RefinedTypeOps.Transparent[T]
and RefinedTypeOpsImpl[A, C, T]
becomes RefinedTypeOps[A, C, T]
. Note that this introduces a minor compatibility break with 2.2.1.
It is recommended (but not mandatory) to use RefinedTypeOps.Transparent
for transparent type aliases. Opaque types should use the more verbose RefinedTypeOps[A, C, T]
.
For examples, this code written with Iron 2.2.1:
opaque type Temperature = Double :| Positive
object Temperature extends RefinedTypeOpsImpl[Double, Positive, Temperature]
type Age = Double :| Positive
object Age extends RefinedTypeOps[Age]
becomes in 2.3.0:
opaque type Temperature = Double :| Positive
object Temperature extends RefinedTypeOps[Double, Positive, Temperature]
type Age = Double :| Positive
object Age extends RefinedTypeOps.Transparent[Age]
This change brings several improvements:
- Compatibility with future versions of Scala. See scala/scala3#17984
- Improvements on
RefinedTypeOps
companion's given instances. They no longer are orphans and nogiven
import should be needed anymore.
New TypeTest
given instances
The RefinedTypeOps
trait (and IronType
) now brings TypeTest
instances. This is especially be useful in some typeclass derivation scenarios.
Runtime proxy for constraints
RuntimeConstraint[A, C]
is a proxy for Constraint[A, C]
usable at runtime. It significantly lowers the quantity of generated bytecode (by generating test
. Unlike Constraint
, a RuntimeConstraint
given instance does not require the method to be inline
:
//Compiles without `inline`
def refineOption[A, C](value: A)(using constraint: RuntimeConstraint[A, C]): Option[A :| C] =
Option.when(constraint.test(value))(value.asInstanceOf[A :| C])
refineOption[Int, Positive](5) //Some(5)
refineOption[Int, Positive](-5) //None
Note that RefinedTypeOps
also makes use of it by reusing the same instance of RuntimeConstraint
for companion object's methods (option
, either
, ...).
Ciris support
A new iron-ciris
module (JVM/SJS/SN) has been added, providing typeclass instances for Ciris. For example:
import cats.syntax.all.*
import ciris.*
import io.github.iltotore.iron.*
import io.github.iltotore.iron.constraint.all.*
import io.github.iltotore.iron.cats.given
import io.github.iltotore.iron.ciris.given
type Username = String :| (Not[Blank] & MaxLength[32])
type Password = String :| (Not[Blank] & MinLength[9])
case class DatabaseConfig(username: Username, password: Secret[Password])
val databaseConfig: ConfigValue[Effect, DatabaseConfig] = (
env("DB_USERNAME").as[Username],
env("DB_PASSWORD").as[Password].secret
).mapN(DatabaseConfig.apply)
Both IronType
and RefinedTypeOps
are supported.
Circe key support
iron-circe
now provides KeyEncoder
/KeyDecoder
instances given instances for refined types and new types.
Upgrade to Scala 3.3.1
Iron now uses Scala 3.3.1. The plan is to stick to the latest LTS version of Scala. See Scala's long-term compatibility plans.
This will require the consumers to update to Scala 3.3.1 or older to use Iron. The change should not break anything with Iron or other source code wrote in 3.2.x.
Adopters
Ledger was added to the list of adopters.
Contributors
- @ajaychandran: #179
- @kyri-petrou: #154, #175 and #176
- @rparree: #163
- @vbergeron: #182 and #183
- @Zelenya: #148
Full Changelog: v2.2.1...v2.3.0