https://github.com/note/mini-refined
Simple encoding of refinement types in Scala 3
https://github.com/note/mini-refined
Last synced: about 1 year ago
JSON representation
Simple encoding of refinement types in Scala 3
- Host: GitHub
- URL: https://github.com/note/mini-refined
- Owner: note
- License: mit
- Created: 2021-04-30T05:17:48.000Z (about 5 years ago)
- Default Branch: main
- Last Pushed: 2024-06-24T11:55:01.000Z (almost 2 years ago)
- Last Synced: 2025-04-08T01:01:39.859Z (about 1 year ago)
- Language: Scala
- Homepage:
- Size: 101 KB
- Stars: 25
- Watchers: 4
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# mini-refined
[](https://github.com/note/mini-refined/actions)
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](https://msitko.pl/blog/build-your-own-refinement-types-in-scala3.html).
## Quick start
Include library in `build.sbt`:
```
libraryDependencies += "pl.msitko" %% "mini-refined" % "0.2.0"
```
Common imports:
```scala
import pl.msitko.refined.auto._
import pl.msitko.refined.Refined
```
### Circe integration
To use circe integration:
```
libraryDependencies += "pl.msitko" %% "mini-refined-circe" % "0.2.0"
```
## Int predicates
```scala
val a: Int Refined GreaterThan[10] = 5
// fails compilation with: Validation failed: 5 > 10
```
```scala
val a: Int Refined LowerThan[10] = 15
// fails compilation with: Validation failed: 15 < 10
```
## String predicates
```scala
val s: String Refined StartsWith["xyz"] = "abc"
// fails compilation with: Validation failed: abc.startsWith(xyz)
```
```scala
val s: String Refined EndsWith["xyz"] = "abc"
// fails compilation with: Validation failed: abc.endsWith(xyz)
```
## List predicates
```scala
val as: List[String] Refined Size[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:
```scala
val c: Int Refined And[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:
```scala
case class Example(a: Int, b: Int Refined GreaterThan[10])
def runtime(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:
```scala
def intFun10(a: Int Refined GreaterThan[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.