jon.recoil.org

Module ValidateSource

A module for organizing validations of data structures.

Allows standardized ways of checking for conditions, and keeps track of the location of errors by keeping a path to each error found. Thus, if you were validating the following datastructure:

  { foo = 3; bar = { snoo = 34.5; blue = Snoot - 6 } }

One might end up with an error with the error path:

bar.blue.Snoot : value -6 <= bound 0

By convention, the validations for a type defined in module M appear in module M, and have their name prefixed by validate_. E.g., Int.validate_positive.

Here's an example of how you would use validate with a record:

  type t =
    { foo : int
    ; bar : float
    }
  [@@deriving fields ~iterators:to_list]

  let validate t =
    let module V = Validate in
    let w check = V.field check t in
    Fields.to_list ~foo:(w Int.validate_positive) ~bar:(w Float.validate_non_negative)
    |> V.of_list
  ;;

And here's an example of how you would use it with a variant type:

  type t =
    | Foo of int
    | Bar of (float * int)
    | Snoo of Floogle.t

  let validate = function
    | Foo i -> V.name "Foo" (Int.validate_positive i)
    | Bar p ->
      V.name
        "Bar"
        (V.pair ~fst:Float.validate_positive ~snd:Int.validate_non_negative p)
    | Snoo floogle -> V.name "Snoo" (Floogle.validate floogle)
  ;;
Sourcetype t

The result of a validation. This effectively contains the list of errors, qualified by their location path

Sourcetype ('a : any) check__portable = 'a -> Validate.t @ portable

To make function signatures easier to read.

Sourceand ('a : any) check = 'a -> Validate.t

To make function signatures easier to read.

(check[@mode portable]) can be read as "a check that returns a Validate.t at mode portable".

If you have f of type (check[@mode portable]), sometimes the type checker takes some convincing to treat it as a check, even though a returning-at-portable function is morally a subtype of a returning-at-nonportable function. Writing (fun x -> f x) should be enough to convert the (check[@mode portable]) into a check.

Sourceval pass : Validate.t @@ portable

A result containing no errors.

Sourceval get_pass : Base.unit -> Validate.t @ portable @@ portable
Sourceval fail : Base.string -> Validate.t @ portable @@ portable

A result containing a single error.

Sourceval fails : Base.string -> 'a -> ('a -> Base.Sexp.t) -> Validate.t @@ portable
Sourceval fail_s : Base.Sexp.t -> Validate.t @ portable @@ portable

This can be used with the %sexp extension.

Sourceval failf : ('a, Base.unit, Base.string, Validate.t) Base.format4 -> 'a @@ portable

Like sprintf or failwithf but produces a t instead of a string or exception.

Sourceval combine : Validate.t -> Validate.t -> Validate.t @@ portable
Sourceval of_list : Validate.t Base.list -> Validate.t @@ portable

Combines multiple results, merging errors.

Sourceval name : Base.string -> Validate.t -> Validate.t @@ portable

Extends location path by one name.

Sourceval lazy_name : Base.string Base.Lazy.t -> Validate.t -> Validate.t @@ portable

Extends location path by one lazy name, which will be forced only in the case of failure.

Sourceval name_list : Base.string -> Validate.t Base.list -> Validate.t @@ portable
Sourceval lazy_name_list : Base.string Base.Lazy.t -> Validate.t Base.list -> Validate.t @@ portable
Sourceval fail_fn : Base.string -> _ Validate.check @ portable @@ portable

fail_fn err returns a function that always returns fail, with err as the error message. (Note that there is no pass_fn so as to discourage people from ignoring the type of the value being passed unconditionally irrespective of type.)

Sourceval pass_bool : Base.bool Validate.check @@ portable

Checks for unconditionally passing a bool.

Sourceval pass_unit : Base.unit Validate.check @@ portable

Checks for unconditionally passing a unit.

Sourceval protect : ('a : value_or_null). 'a Validate.check -> 'a Validate.check @@ portable

protect f x applies the validation f to x, catching any exceptions and returning them as errors.

Sourceval try_with : (Base.unit -> Base.unit) -> Validate.t @@ portable

try_with f runs f catching any exceptions and returning them as errors.

Sourceval result : Validate.t -> Base.unit Base.Or_error.t @@ portable
Sourceval errors : Validate.t -> Base.string Base.list @@ portable

Returns a list of formatted error strings, which include both the error message and the path to the error.

Sourceval maybe_raise : Validate.t -> Base.unit @@ portable

If the result contains any errors, then raises an exception with a formatted error message containing a message for every error.

Sourceval valid_or_error : 'a Validate.check -> 'a -> 'a Base.Or_error.t @@ portable

Returns an error if validation fails.

Sourceval field : ('a : value_or_null) 'record. 'a Validate.check -> 'record -> ([> `Read ], 'record, 'a) Base.Field.t_with_perm -> Validate.t @@ portable

Used for validating an individual field. Should be used with Fields.to_list.

Sourceval field_direct : ('a : value_or_null) 'record. 'a Validate.check -> ([> `Read ], 'record, 'a) Base.Field.t_with_perm -> 'record -> 'a -> Validate.t @@ portable

Used for validating an individual field. Should be used with Fields.Direct.to_list.

Sourceval field_folder : 'a Validate.check -> 'record -> Validate.t Base.list -> ([> `Read ], 'record, 'a) Base.Field.t_with_perm -> Validate.t Base.list @@ portable

Creates a function for use in a Fields.fold.

Sourceval portable_field_folder : 'a Validate.check__portable -> 'record -> Validate.t Base.portable Base.list -> ([> `Read ], 'record, 'a) Base.Field.t_with_perm -> Validate.t Base.portable Base.list @@ portable

Like field_folder, but for producing a list of portable ts. It's marginally easier to use directly when folding over fields to produce a portable result.

Sourceval field_direct_folder : 'a Validate.check -> (Validate.t Base.list -> ([> `Read ], 'record, 'a) Base.Field.t_with_perm -> 'record -> 'a -> Validate.t Base.list) Base.Staged.t @@ portable

Creates a function for use in a Fields.Direct.fold.

Sourceval all : 'a Validate.check Base.list -> 'a Validate.check @@ portable

Combines a list of validation functions into one that does all validations.

Sourceval of_result : ('a -> (Base.unit, Base.string) Base.Result.t) -> 'a Validate.check__portable @@ portable

Creates a validation function from a function that produces a Result.t.

Sourceval of_error : ('a -> Base.unit Base.Or_error.t) -> 'a Validate.check @@ portable
Sourceval booltest : ('a -> Base.bool) -> if_false:Base.string -> 'a Validate.check @@ portable

Creates a validation function from a function that produces a bool.

Sourceval lazy_booltest : ('a -> Base.bool) -> if_false:Base.string Base.Lazy.t -> 'a Validate.check @@ portable

Creates a validation function from a function that produces a bool. Forces the name only when validation fails.

Sourceval pair : fst:'a Validate.check -> snd:'b Validate.check -> ('a * 'b) Validate.check @@ portable

Validation functions for particular data types.

Sourceval list_indexed : 'a Validate.check -> 'a Base.list Validate.check @@ portable

Validates a list, naming each element by its position in the list (where the first position is 1, not 0).

Sourceval list : name:('a -> Base.string) -> 'a Validate.check -> 'a Base.list Validate.check @@ portable

Validates a list, naming each element using a user-defined function for computing the name.

Sourceval first_failure : Validate.t -> Validate.t -> Validate.t @@ portable
Sourceval of_error_opt : Base.string Base.option -> Validate.t @ portable @@ portable
Sourceval alist : name:('a -> Base.string) -> 'b Validate.check -> ('a * 'b) Base.list Validate.check @@ portable

Validates an association list, naming each element using a user-defined function for computing the name.

Sourceval bounded : name:('a -> Base.string) -> lower:'a Base.Maybe_bound.t -> upper:'a Base.Maybe_bound.t -> compare:('a -> 'a -> Base.int) -> 'a Validate.check__portable @@ portable
Sourcemodule Infix : sig ... end