Reusable predicate layer with the Check module.
Pure Checks
Check<'value> is the foundation of FsFlow validation. It is a reusable predicate layer that returns Result<'value, unit>.
- If the predicate is true, it returns
Ok value. - If the predicate is false, it returns
Error ().
By returning unit on failure, Check stays agnostic about your application’s error types. You decide what the error means at the boundary where you use it.
The Two Shapes of Check
- Value-Preserving:
Check<'value>- returns the input value on success.let check = Check.notBlank // string -> Result<string, unit> - Gate:
Check<unit>- returnsuniton success (useful for yes/no questions).let check = Check.okIf (age > 18) // unit -> Result<unit, unit>
Attaching Errors with Check.orError
Use Check.orError to turn a unit failure into a meaningful application error.
type ValidationError =
| NameRequired
| InvalidAge
let validateName name =
name |> Check.notBlank |> Check.orError NameRequired
let validateAge age =
age |> Check.okIf (age > 0) |> Check.orError InvalidAge
Common Helpers
The Check module includes many built-in helpers:
Check.notBlank,Check.notNull,Check.notEmptyCheck.okIf,Check.failIfCheck.equal,Check.notEqualCheck.okIfSome,Check.okIfValueSome
Why use Checks?
- Reusability: Write a check once, use it in
result {},validate {}, or any Flow. - Composition: You can combine checks using
Check.andandCheck.or. - Decoupling: Pure logic doesn’t need to know about your logging or your database.