Go Refined is a minimalistic type-refinement library. It is a partial port of Frank Tomas's Scala refined library and Nikita Volkov's Haskell refined library. It is used to express constraints on type by using type-level predicates.
package example
import r "github.com/valentinHenry/refined"
pi, err := r.Refine[int, r.Positive](2)
// pi.Value() == 2, err == nil
pi, err = r.Refine[int, r.Positive](0)
// err == NonComplianceError
// err.Error() == "value 0 does not comply with the predicate refined.Positive"
// Because go does not have type-level numbers yet, it is necessary to implement the TNumber interface
type N15[N Number] struct{}
func (n N15) Of() N { return 15 }
pj, err = r.Refine[float32, r.LessThan[float32, N15]](12.345)
// pj.Value() == 12.345
pk, err = r.Refine[float32, r.LessThan[uint32, N15]](42)
// err == NonComplianceError
// err.Error() == "value 0 does not comply with the predicate refined.Positive"
str, err := r.Refine[string, r.And[r.NonEmpty, r.Trimmed]]("Hello")
// str.Value() == "Hello"
str, err = r.Refine[string, refined.And[r.NonEmpty, r.Trimmed]](" hello")
// err == NonComplianceError
// err.Error() == "value 0 does not comply with the predicate ..."
str, err = r.Refine[string, refined.And[r.NonEmpty, r.Trimmed]]("")
// err == NonComplianceError
// err.Error() == "value 0 does not comply with the predicate ..."
func OnSmallSlices(s r.Refined[[]int, r.SizeLessThan[r.N4[int]]]) {
for _, i2 := range s.Value() {
fmt.Println(i2)
}
}
items := []int{1, 2, 3}
ritems, err := r.Refine[[]int, r.SizeLessThan[r.N4[int]]](items)
// ritems.Value() == []int{1, 2, 3}
OnSmallSlices(ritems) // Compiles
items = []int{1, 2, 3, 4}
ritems, err := r.Refine[[]int, r.SizeLessThan[r.N5[int]]](items)
// ritems.Value() == []int{1, 2, 3}
OnSmallSlices(ritems) // Does not compile (bad type)
And
: the predicate1 AND predicate2Or
: the predicate1 OR predicate`Not
: negate a predicateXor
: predicate1 XOR predicate2 (p1 && !p2) || (!p1 && p2)
EndsWith
: checks if a string ends with the suffix SStartsWith
: checks if a string starts with the prefix SRegex
: checks if a string is a valid regexMatchesRegex
: checks if a string matched the regex RValidInt
: checks if a string is an int ~> int64ValidFloat
: checks if a string is a float32 and/or a float64Trimmed
: checks if a string does not have leading and trailing whitespacesEmpty
: checks if a string is emptyNonEmpty
: checks if a string is non-empty
int
| int8
| int32
| int64
| float32
| float64
| uint
| uint8
| uint16
| uint32
| uint64
Positive
: checks if a number is >= 1Negative
: checks if a number is <= -1 (always false for unsigned)NonNegative
: checks if a number is >=0 (always true for unsigned)NonPositive
: checks if a number is <=0LessThan
: checks if a number is < NBGreaterThan
: checks if a number is > NBFrom
: checks if a number is >= NBTo
: checks if a number is <= NBFromTo
: checks if a number is between[LNB, RNB]
(LNB <= x <= RNB)Between
: checks if a number is between]LNB, RNB[
(LNB < x < RNB)FromUntil
: checks if a number is between[LNB, RNB[
(LNB <= x < RNB)AfterTo
: checks if a number is between]LNB, RNB]
(LNB < x <= RNB)
Empty
: checks if a collection is emptyNonEmpty
: checks if a collection is not emptySizeLessThan
: checks if the size of the collection is less(strict) than NSizeGreaterThan
: checks if the size of the collection is greater(strict) than NSizeEqualTo
: checks if the size of the collection is equal to N