A lightweight reactive document library.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

135 lines
4.4 KiB

  1. type +'a t
  2. (** A dynamic document of type ['a]. Documents can be produced in several
  3. different ways:
  4. - operators, such as {!map}, {!bind}, {!app}, {!pair}, etc.
  5. combine several documents into one. The result is (lazily)
  6. updated whenever the sub-documents are.
  7. - variables {!var}, a mutable reference.
  8. - primitive documents {!prim}, providing custom leaves to trees of
  9. documents.
  10. *)
  11. val return : 'a -> 'a t
  12. (** The content document with the given value inside *)
  13. val pure : 'a -> 'a t
  14. (** Alias to {!return} *)
  15. val map : ('a -> 'b) -> 'a t -> 'b t
  16. (** [map f d] is the document that has value [f x] whenever [d] has value [x] *)
  17. val map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t
  18. (** [map2 f d1 d2] is the document that has value [f x y] whenever
  19. [d1] has value [x1] and [d2] has value [x2] *)
  20. val map' : 'a t -> ('a -> 'b) -> 'b t
  21. (** Alias to {!map} with arguments flipped *)
  22. val map2' : 'a t -> 'b t -> ('a -> 'b -> 'c) -> 'c t
  23. (** Alias to {!map2} with arguments flipped *)
  24. val join : 'a t t -> 'a t
  25. (** Monadic operator [join d] is the document pointed to by document [d].
  26. This is powerful but potentially costly in case of recomputation.
  27. *)
  28. val bind : 'a t -> ('a -> 'b t) -> 'b t
  29. (** Monadic bind, a mix of {!join} and {!map} *)
  30. val app : ('a -> 'b) t -> 'a t -> 'b t
  31. (** Applicative: [app df dx] is the document that has value [f x]
  32. whenever [df] has value [f] and [dx] has value [x] *)
  33. val pair : 'a t -> 'b t -> ('a * 'b) t
  34. (** [pair a b] is [map2 (fun x y->x,y) a b] *)
  35. val impure : 'a t -> 'a t
  36. val is_pure : 'a t -> 'a option
  37. type 'a var
  38. (** The workhorse of Lwd: a mutable variable that also tracks dependencies.
  39. Every time {!set} is called, all documents that depend on this variable
  40. via {!map}, {!bind}, etc. will be at least partially invalidated
  41. and will be recomputed incrementally on demand. *)
  42. val var : 'a -> 'a var
  43. (** Create a new variable with the given initial value *)
  44. val get : 'a var -> 'a t
  45. (** A document that reflects the current content of a variable *)
  46. val set : 'a var -> 'a -> unit
  47. (** Change the variable's content, invalidating all documents depending
  48. on it. *)
  49. val peek : 'a var -> 'a
  50. (** Observe the current value of the variable, without any dependency
  51. tracking. *)
  52. type +'a prim
  53. (** A primitive document. It can correspond, for example, to
  54. a primitive UI element.
  55. A primitive is a resource with [acquire] and [release] functions
  56. to manage its lifecycle. *)
  57. val prim : acquire:(unit -> 'a) -> release:('a -> unit) -> 'a prim
  58. (** create a new primitive document.
  59. @param acquire is called when the document becomes observed (indirectly)
  60. via at least one {!root}.
  61. @param release is called when the document is no longer observed.
  62. Internal resources can be freed. *)
  63. val get_prim : 'a prim -> 'a t
  64. val invalidate : 'a prim -> unit
  65. (** Releasing unused graphs *)
  66. type release_failure = exn * Printexc.raw_backtrace
  67. exception Release_failure of exn option * release_failure list
  68. type release_queue
  69. val make_release_queue : unit -> release_queue
  70. val flush_release_queue : release_queue -> release_failure list
  71. type +'a root
  72. (** A root of computation, whose value(s) over time we're interested in. *)
  73. val observe : ?on_invalidate:('a -> unit) -> 'a t -> 'a root
  74. (** [observe x] creates a root that contains document [x].
  75. @param on_invalidate is called whenever the root is invalidated
  76. because the content of [x] has changed. This can be useful to
  77. perform side-effects such as re-rendering some UI. *)
  78. val set_on_invalidate : 'a root -> ('a -> unit) -> unit
  79. (** Change the callback for the root.
  80. @see observe for more details. *)
  81. val sample : release_queue -> 'a root -> 'a
  82. (** Force the computation of the value for this root.
  83. The value is cached, so this is idempotent, until the next invalidation. *)
  84. val is_damaged : 'a root -> bool
  85. (** [is_damaged root] is true if the root doesn't have a valid value in
  86. cache. This can be the case if the value was never computed, or
  87. if it was computed and then invalidated. *)
  88. val release : release_queue -> 'a root -> unit
  89. (** Forget about this root and release sub-values no longer reachable from
  90. any root. *)
  91. val quick_sample : 'a root -> 'a
  92. val quick_release : 'a root -> unit
  93. module Infix : sig
  94. val (>|=) : 'a t -> ('a -> 'b) -> 'b t
  95. val (>>=) : 'a t -> ('a -> 'b t) -> 'b t
  96. val (<*>) : ('a -> 'b) t -> 'a t -> 'b t
  97. end
  98. (* For debug purposes *)
  99. val dump_trace : 'a t -> unit