Up

Module type Invariant

Signature

type 'a t = 'a t
module type S = S
module type S1 = S1
module type S2 = S2
module type S3 = S3
val invariant : Source_code_position0.t -> 'a -> ('a -> Sexplib.Sexp.t) -> (unit -> unit) -> unit

invariant here t sexp_of_t f runs f (), and if f raises, wraps the exception in an Error.t that states "invariant failed" and includes both the exception raised by f, as well as sexp_of_t t. Idiomatic usage looks like:


        invariant [%here] t <:sexp_of< t >> (fun () ->
          ... check t's invariants ... )
      

For polymorphic types:


        let invariant check_a t =
          Invariant.invariant [%here] t <:sexp_of< _ t >> (fun () -> ... )
      

It's okay to use <:sexp_of< _ t >> because the exceptions raised by check_a will show the parts that are sexp_opaque at top-level.

val check_field : 'a -> 'b t -> ('a, 'b) Fieldslib.Field.t -> unit

check_field is used when checking invariants using Fields.iter. It wraps an exception raised when checking a field with the field's name. Idiomatic usage looks like:


        type t =
          { foo : Foo.t;
            bar : Bar.t;
          }
        with fields

        let invariant t : unit =
          invariant "Foo.invariant" t <:sexp_of< t >> (fun () ->
            let check f = Invariant.check_field t f in
            Fields.iter
              ~foo:(check Foo.invariant)
              ~bar:(check Bar.invariant))
        ;;