Repository F# setup
open Reified
open Reified.Refinements
open Reified.Result

The key catalogue

Every key Reified can produce. actual is not listed as an argument on any predicate: it arrives through the separate constraint.actual entry.

Key Arguments Plural on Default English
constraint.presence.present — — must be present
constraint.presence.blank — — must be blank
constraint.cardinality.exact expected expected must have a size of exactly
constraint.cardinality.minimum minimum minimum must have a size of at least
constraint.cardinality.maximum maximum maximum must have a size of at most
constraint.cardinality.between minimum, maximum — must have a size between and
constraint.relation.equal expected — must be
constraint.relation.notEqual expected — must not be
constraint.relation.greaterThan expected — must be greater than
constraint.relation.lessThan expected — must be less than
constraint.relation.atLeast expected — must be at least
constraint.relation.atMost expected — must be at most
constraint.relation.within minimum, maximum — must be between and
constraint.membership.oneOf choices — must be one of
constraint.membership.noneOf choices — must not be one of
constraint.membership.contains item — must contain
constraint.membership.notContains item — must not contain
constraint.uniqueness — — must not contain duplicate values
constraint.format.email — — must be an email address
constraint.format.trimmed — — must not have leading or trailing whitespace
constraint.format.numeric — — must contain digits only
constraint.format.alphanumeric — — must contain letters and digits only
constraint.format.pattern pattern — must match
constraint.number.multipleOf divisor — must be a multiple of
constraint.number.finite — — must be a finite number

A built-in whose operand Reified cannot describe reports the relation rather than approximating the operand. These carry no arguments:

Key Arguments Plural on Default English
constraint.unsupportedOperand.relation.equal — — must equal the required value
constraint.unsupportedOperand.relation.notEqual — — must not equal the excluded value
constraint.unsupportedOperand.relation.greaterThan — — must be greater than the required value
constraint.unsupportedOperand.relation.lessThan — — must be less than the required value
constraint.unsupportedOperand.relation.atLeast — — must be at least the required value
constraint.unsupportedOperand.relation.atMost — — must be at most the required value
constraint.unsupportedOperand.within — — must be within the required range
constraint.unsupportedOperand.contains — — must contain the required value
constraint.unsupportedOperand.multipleOf — — must be a multiple of the required value

The composition and joining entries:

Key Arguments Plural on Default English
constraint.attribute.default — — value
constraint.actual message, actual — , but was
constraint.fullMessage attribute, message —
constraint.group.all.pair first, second — and
constraint.group.all.start first, rest — ,
constraint.group.all.middle first, rest — ,
constraint.group.all.end first, second — and
constraint.group.any.pair first, second — or
constraint.group.any.start first, rest — ,
constraint.group.any.middle first, rest — ,
constraint.group.any.end first, second — or
constraint.list.pair first, second — and
constraint.list.start first, rest — ,
constraint.list.middle first, rest — ,
constraint.list.end first, second — and

The same data is available at runtime, so a coverage test never has to copy this page:

Catalogue.keys            // string list
Catalogue.arguments       // Map<string, string list>
Catalogue.english         // Map<string, string>
Catalogue.pluralArgument  // Map<string, string option>

A test enumerates the atom union against both this page and Catalogue, so a new rule cannot ship with its key undocumented or unimplemented.

Argument values

Arguments are ConstraintValue, the closed value model every interpreter understands: text, char, boolean, integer, decimal, big integer, float, GUID, timespan, date-time, date-time-offset, null, and lists of those. ConstraintValue.render gives the invariant rendering of one; a renderer formats through its value culture instead.