Skip to content

Repository files navigation

mini-refined

example workflow

A proof of concept of a simple encoding of refinement types in Scala 3.

You can read about motivation behind and the main concepts in the blog post.

Quick start

Include library in build.sbt:

libraryDependencies += "pl.msitko" %% "mini-refined" % "0.2.0"

Common imports:

importpl.msitko.refined.auto._importpl.msitko.refined.Refined

Circe integration

To use circe integration:

libraryDependencies += "pl.msitko" %% "mini-refined-circe" % "0.2.0"

Int predicates

vala:IntRefinedGreaterThan[10] =5// fails compilation with: Validation failed: 5 > 10
vala:IntRefinedLowerThan[10] =15// fails compilation with: Validation failed: 15 < 10

String predicates

vals:StringRefinedStartsWith["xyz"] ="abc"// fails compilation with: Validation failed: abc.startsWith(xyz)
vals:StringRefinedEndsWith["xyz"] ="abc"// fails compilation with: Validation failed: abc.endsWith(xyz)

List predicates

valas:List[String] RefinedSize[GreaterThan[1]] =List("a")
// fails compilation with: // Validation failed: list size doesn't hold predicate: 1 > 1

You can use any Int predicates within Size predicate.

Compose predicates with boolean operators

You can compose predicates with boolean operators. For example:

valc:IntRefinedAnd[GreaterThan[10], LowerThan[20]] =25// fails compilation with: Validation failed: (25 > 10 And 25 < 20), predicate failed: 25 < 20

Runtime validation

Everything described so far works only for values known at a compile-time. However, values for most variables are coming at runtime. For those you need to use Refined.refineV[T] which returns Either[String, T]. Example:

caseclassExample(a: Int, b: IntRefinedGreaterThan[10])
defruntime(a: Int, b: Int):Either[String, Example] =Refined.refineV[GreaterThan[10]](b).map(refined =>Example(a, refined))

Inferring types compatibility

mini-refined has some basic rules that enable using more specific types in places where more general types are required.

In other words, considering such function:

defintFun10(a: IntRefinedGreaterThan[10]):Unit=???

We can call it with a value of type Int Refined GreaterThan[20], as mini-refined recognizes that being greater than 20 implies being greater than 10.

About

Simple encoding of refinement types in Scala 3

Resources

Stars

23 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages