Releases: Iltotore/iron
v2.0.0-RC1
Introduction
This the first pre-release of Iron 2.
The project was rebuilt from scratch on a better foundation. This breaks code using Iron 1.x. You should expect better stability after 2.0.0 release.
Note: the API is still subject to change until 2.0.0 get released.
New website
A microsite containing Scaladoc and static documentation/tutorials is available at https://iltotore.github.io/iron/docs/.
Main changes
- Use Scala 3.2.x. to benefit from several fixes. All versions >= 3.2.0 are supported.
- Refined types are no longer either-based. An IronType is now a subtype of its "raw" version. For example,
IronType[Int, Greater[0]]
is a subtype ofInt
. No overhead anymore, no virality. - Compile-time refinement is stricter. Compile-time refinement has to be proven at compile-time. Use
refine
,refineEither
orrefineOption
instead. - Implications (new version of Consequences) are now stable. Easily make simple or complex implications between constraints.
- Support type union and intersection. Say goodbye to
Or
andAnd
constraints! - Better error messages. Now exactly what's happening and debug constraints more easily.
- Numeric, String and Collection constraints are now in the main module. IO got dropped, Cats and Circe (and new ZIO-JSON support) are still external.
- Compile-time utilities. Available in
io.github.iltotore.iron.compileTime
.
Note: a richer changelog about Iron 2 will be published once 2.0.0 is released.
Full Changelog: v1.2.0...v2.0.0-RC1
Coming soon
- Example projects including some using external modules like Cats support, ZIO-JSON support or Circe support.
- Documentation polishing to make it more guided.
- Articles
Contributors
- @SethTisue: README grammar/vocabulary fixes (#56)
- @andrzejressel: Compile-time String constraints for 1.x, reused in 2.0.0 (#44)
Iron v1.2.0
Introduction
This release polishes v1.1.2 and adds a new alternative DSL.
Features
Imperative DSL
A capability to use refined types in an imperative-style. Based on HOPE 2021 Martin Odersky's talk:
//Monadic version
def log(x: Double > 0d): Refined[Double] = x.map(Math.log)
//Imperative version
def log(x: Double > 0d): Raw[Double] = refined {
Math.log(x)
}
Note: Raw[Double]
is a value contrained by an always-valid constraint. It is different from Refined[Double]
which is an alias for Either[IllegalValueError, Double]
more interoperability between Constrained
and monads will be added in 2.0.0 due to possible breaking changes.
Consequences
A constrained-to-constrained version of constraints (which are value-to-constrained). It allows refinements of already-constrained variables and use relations to avoid unnecessary evaluation:
val x: Double < 5d = 3d
val y: Double < 10d = x //5d < 10d will be verified at compile-time
val a: Double / Less[5d] = 3d
val b: Double / Not[Less[5d]] = a //Fails at compile time
See the wiki for further information.
Note: this works with all kind of constraints. Not only numeric.
Due to a compiler limitation, some "complex" consequences cannot be created yet.
Planned for 2.0.0
The next major release (2.0.0) will contain the following features:
- Polishing of the current API (simplification and standardisation of the current API, hiding internal components etc...)
- More interoperability between Constrained and other monads
- Better compile-time evaluation (keep in mind the inner value of a
Constrained
at compile-time if exists, more out of the box Consequences etc...)
Happy new year 🎉
Iron v1.1.2
Introduction
This release adds multiple improvements to Iron without breaking changes.
Features
New alias for Constrained[A, B]
The old alias A ==> B
is replaced by A / B
to fit the set notation in maths: S / P(x)
Algebra system
A new algebra system that allows user to chain operators of the same algebra type and to write their constraints in a more mathematical way.
From #35 :
- Add placeholder type
??
. Other candidates?
,_
and???
are already taken. - Constraints can now belong to a specific algebra
- Algebra entry points can be used with the
??
placeholder:Double / (-1d < ?? < 1d)
desugars toDouble / (Greater[-1d] && Less[1d])
. It is also possible to use different constraints as long as they belong to the same algebra. - Algebra elements of the same type can be chained.
-1d < ?? < 1d < 2d < ...
.
Note: chaining is disallowed in before the placeholder??
to keep allowingDouble < 1d
and similar syntax. For example,-1 < ??
is allowed but-2d < -1d < ??
isn't.
Composed constraints now support compile-time evaluation
And
, Not
, Or
and similar constraints can now be evaluated at compile-time. Example:
def foo(x: Double / (Divisible[2d] && Greater[0d])): Unit = ???
foo(1d) //compile-time error
foo(-2d) //compile-time error
foo(2d) //This is fine
Iron Numeric
Iron numeric was updated to take advantage of the mentioned features. Version of this update: 1.1-1.0.1
Test it
Here is an interactive example using the described changes.
Code
import io.github.iltotore.iron.*, constraint.{*, given}, numeric.constraint.{*, given}
def acos(x: Double / ((-1d <= ?? <= 1d) DescribedAs "x should be a cosinus")): Refined[Double] = x.map(Math.acos)
println(acos(1d))
Iron v1.1.1
Introduction
This is a condensed of two releases: Iron v1.1.1 and Iron Numeric v1.1-1.0.0
Iron v1.1.1
- Add
RuntimeOnly[B]
modifier. It transforms the wrapped constraint into a runtime only version. - Internal code improvement
Iron Numeric v1.1-1.0.0
Even[A]
in its old state wasn't that useful. The discussion #27 showed that Even
has more use cases as a Constraint than as a Constrained:
type +>[A, B] = A ==> Greater[0] && Even[A]
Even
provides a useful abstraction to support all numeric types.
- Fix wrong type alias for
Natural[T]
Iron IO v0.1.0
The module iron-io
, including IO-related constraints was released under 0.1.0 (full version)
Included constraints:
- IsFile
- IsDirectory
- Exists
Please check the module README for further details.
Iron v1.1
Introduction
This release is a continuation of Iron v1.0 improving error handling and global ecosystem.
Features
Better error handling
- Add
IllegalValueError.Field
, a field-based IllegalValueError. - Errors now have a message instead of a constraint instance.
- Each constraint must have a description by overriding
Constraint#getMessage
- You can attach a custom description to an existing constraint using
DescribedAs[B, V]
. See the wiki - Accumulative Error Handling via Cats. See the Extra Modules section below.
Extra Modules
Fixes
- Alphanumeric now matches upper-cased characters
Example
An example project is now available. Further details in future articles.
Iron v1.0
Introdution
This is the first major release of Iron. This version includes many enhancements and new modules.
Features
Constraint results are now Either-based
This change allows functional error handling and better synergy with functional libraries like Cats.
An example of functional usage of Iron:
case class Account(username: String, email: String, password: String)
object Account {
//Here, the Match[String] constraint isn't natively implemented in Iron and is only used as example.
//Type aliases are not mandatory. They can be used for readability purpose.
type Username = String ==> Match["^[a-zA-Z0-9]+"]
type Email = String ==> Match["^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$"]
//At least one upper, one lower and one number
type Password = String ==> Match["^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])[a-zA-Z0-9]+"]
def createAccount(username: Username, email: Email, password: Password): Either[IllegalValueError[String], Account] = for {
a <- username
b <- email
c <- password
} yield Account(a, b, c)
}
Constraint composition
The main module now includes basic operations to compose constraints:
- Not[B]
- And[B, C]
- Or[B, C]
Extra modules
Iron now have the following modules:
Configurable evaluation behaviour
You can now configure evaluation individually using Constraint.CompileTimeOnly
and Constraint.RuntimeOnly
.
Future
Currently planned change are:
- New modules for some projects like Cats and some serialization libraries (Circe, etc...)
- A video presentation of Iron.
For further informations about installing, check the README.