
 type +'a t
 (** A dynamic document of type ['a]. Documents can be produced in several
 different ways:

  operators, such as {!map}, {!bind}, {!app}, {!pair}, etc.
 combine several documents into one. The result is (lazily)
 updated whenever the subdocuments are.

  variables {!var}, a mutable reference.
  primitive documents {!prim}, providing custom leaves to trees of
 documents.
 *)

 val return : 'a > 'a t
 (** The content document with the given value inside *)

 val pure : 'a > 'a t
 (** Alias to {!return} *)

 val map : ('a > 'b) > 'a t > 'b t
 (** [map f d] is the document that has value [f x] whenever [d] has value [x] *)

 val map2 : ('a > 'b > 'c) > 'a t > 'b t > 'c t
 (** [map2 f d1 d2] is the document that has value [f x y] whenever
 [d1] has value [x1] and [d2] has value [x2] *)

 val map' : 'a t > ('a > 'b) > 'b t
 (** Alias to {!map} with arguments flipped *)

 val map2' : 'a t > 'b t > ('a > 'b > 'c) > 'c t
 (** Alias to {!map2} with arguments flipped *)

 val join : 'a t t > 'a t
 (** Monadic operator [join d] is the document pointed to by document [d].
 This is powerful but potentially costly in case of recomputation.
 *)

 val bind : 'a t > ('a > 'b t) > 'b t
 (** Monadic bind, a mix of {!join} and {!map} *)

 val app : ('a > 'b) t > 'a t > 'b t
 (** Applicative: [app df dx] is the document that has value [f x]
 whenever [df] has value [f] and [dx] has value [x] *)

 val pair : 'a t > 'b t > ('a * 'b) t
 (** [pair a b] is [map2 (fun x y>x,y) a b] *)

 val impure : 'a t > 'a t
 val is_pure : 'a t > 'a option

 type 'a var
 (** The workhorse of Lwd: a mutable variable that also tracks dependencies.
 Every time {!set} is called, all documents that depend on this variable
 via {!map}, {!bind}, etc. will be at least partially invalidated
 and will be recomputed incrementally on demand. *)

 val var : 'a > 'a var
 (** Create a new variable with the given initial value *)

 val get : 'a var > 'a t
 (** A document that reflects the current content of a variable *)

 val set : 'a var > 'a > unit
 (** Change the variable's content, invalidating all documents depending
 on it. *)

 val peek : 'a var > 'a
 (** Observe the current value of the variable, without any dependency
 tracking. *)

 type +'a prim
 (** A primitive document. It can correspond, for example, to
 a primitive UI element.

 A primitive is a resource with [acquire] and [release] functions
 to manage its lifecycle. *)

 val prim : acquire:(unit > 'a) > release:('a > unit) > 'a prim
 (** create a new primitive document.
 @param acquire is called when the document becomes observed (indirectly)
 via at least one {!root}.
 @param release is called when the document is no longer observed.
 Internal resources can be freed. *)

 val get_prim : 'a prim > 'a t
 val invalidate : 'a prim > unit

 (** Releasing unused graphs *)
 type release_failure = exn * Printexc.raw_backtrace

 exception Release_failure of exn option * release_failure list

 type release_queue
 val make_release_queue : unit > release_queue
 val flush_release_queue : release_queue > release_failure list

 type +'a root
 (** A root of computation, whose value(s) over time we're interested in. *)

 val observe : ?on_invalidate:('a > unit) > 'a t > 'a root
 (** [observe x] creates a root that contains document [x].
 @param on_invalidate is called whenever the root is invalidated
 because the content of [x] has changed. This can be useful to
 perform sideeffects such as rerendering some UI. *)

 val set_on_invalidate : 'a root > ('a > unit) > unit
 (** Change the callback for the root.
 @see observe for more details. *)

 val sample : release_queue > 'a root > 'a
 (** Force the computation of the value for this root.
 The value is cached, so this is idempotent, until the next invalidation. *)

 val is_damaged : 'a root > bool
 (** [is_damaged root] is true if the root doesn't have a valid value in
 cache. This can be the case if the value was never computed, or
 if it was computed and then invalidated. *)

 val release : release_queue > 'a root > unit
 (** Forget about this root and release subvalues no longer reachable from
 any root. *)

 val quick_sample : 'a root > 'a

 val quick_release : 'a root > unit

 module Infix : sig
 val (>=) : 'a t > ('a > 'b) > 'b t
 val (>>=) : 'a t > ('a > 'b t) > 'b t
 val (<*>) : ('a > 'b) t > 'a t > 'b t
 end

 (* For debug purposes *)
 val dump_trace : 'a t > unit
