Krefty is a tool for constructing concrete (refined) types specific for your domain. It uses refinement type theory, i.e. types wrapping a predicate and a value which satisfies it. For DDD users refined types can be viewed as an alternative to value objects or whole objects. Inspired by implementations in haskell and scala.
Also check out values4k which solves the same problem.
implementation("dev.ustits.krefty:krefty-core:<latest_version>")
To refine a type use refined
function with a predicate:
val name = "Krefty" refined NotBlank()
Function will ensure that the value "Krefty"
satisfies the predicate NotBlank
. If not it will cause an error.
Call unrefined
to get the value back:
name.unrefined // "Krefty"
A newly created object can be used to construct new types, for example, by passing it in the constructor:
class NotBlankString private constructor(private val value: String) {
constructor(refined: Refined<NotBlank, String>) : this(refined.unrefined)
}
val notBlank = NotBlankString(refined)
Construct new predicates using delegation:
class UserID : Predicate<Int> by Positive()
val userID = 443812 refined UserID()
Combine predicates using and
, or
functions:
class Percent : Predicate<Int> by GreaterOrEqual(0) and LessOrEqual(100)
val percent = 45 refined Percent()
Or by using All
and Some
classes:
class Percent : Predicate<Int> by All(GreaterOrEqual(0), LessOrEqual(100))
val percent = 45 refined Percent()
Invert predicates with !
function or Not
class:
class NotPercent : Predicate<Int> by !Percent()
// or
class NotPercent : Predicate<Int> by Not(Percent())