Repository F# setup
open Reified
open Reified.Refinements
open Reified.Result
open Reified.Schema.JsonField Blocks and Plain Functions
The inner field block is syntax for transforming one Schema<_> value. It prevents configuration for adjacent fields
from joining into one pipeline.
field _.Email {
withSchema Schema.text
refine ContactEmail.refinement
validate validateCompanyEmail
}Its schema transformation is:
Schema.text
|> Schema.refine ContactEmail.refinement
|> Schema.validate validateCompanyEmailThe outer declaration then attaches that Schema<ContactEmail> to the "email" field and its getter.
withSchema
withSchema replaces canonical type resolution for this field:
field _.Children {
withSchema (Schema.listWith childSchema)
}There is no separate fieldWith declaration. Explicit schema selection is always an operation inside the field.
constrain
Portable constraints can be inspected by JSON Schema, documentation, and UI interpreters:
field _.Name {
constraints [ present; maxLength 80 ]
}The plain function is Schema.constrain.
refine
The plain function receives a descriptor explicitly:
let contactEmailSchema =
Schema.text
|> Schema.refine ContactEmail.refinementInside the field block, either supply the same value or use the destination type's canonical contribution:
field _.Email {
withSchema Schema.text
refine ContactEmail.refinement
}type ContactEmail with
static member Refinement(_: string, _: ContactEmail) = ContactEmail.refinement
field _.Email {
withSchema Schema.text
refine
}The bare form uses the current string schema and the ContactEmail getter type as its compile-time dispatch key.
validate
Executable validation preserves the current type:
let companyEmailSchema =
contactEmailSchema
|> Schema.validate validateCompanyEmailInside the block:
field _.Email {
validate validateCompanyEmail
}Schema attaches the field path if the function fails. Arbitrary executable validation is not emitted as JSON Schema metadata; use a built-in constraint for facts other interpreters must read.