package hardcaml_step_testbench

  1. Overview
  2. Docs

Source file step_monad_intf.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
(** An [('a, 'i, 'o) Step_monad.t] is a description of computation that produces a value
    of type ['a] via a sequential [Component.t] that on each step takes an ['i] and
    produces a ['o].

    The [next_step] operation finishes the current step and pauses until the next step.
    The [spawn] function allows a computation to start other sequential components -- all
    spawned components run in parallel. *)

open! Import

module type Step_monad = sig
  type ('a, 'i, 'o) t [@@deriving sexp_of]

  include Monad.S3 with type ('a, 'b, 'c) t := ('a, 'b, 'c) t

  val next_step : Source_code_position.t -> 'o -> ('i, 'i, 'o) t
  val thunk : (unit -> ('a, 'i, 'o) t) -> ('a, 'i, 'o) t
  val output_forever : 'o -> (_, _, 'o) t

  (** [for_ i j f] does [f i], [f (i+1)], ... [f j] in sequence.  If [j < i], then
      [for_ i j] immediately returns unit. *)
  val for_ : int -> int -> (int -> (unit, 'i, 'o) t) -> (unit, 'i, 'o) t

  (** [delay o ~num_steps] outputs [o] for [num_steps] and then returns unit.  [delay]
      raises if [num_steps < 0]. *)
  val delay : 'o -> num_steps:int -> (unit, _, 'o) t

  (** [repeat ~count f] does [f ()] [count] times.  [repeat] raises if [count < 0]. *)
  val repeat : count:int -> (unit -> (unit, 'i, 'o) t) -> (unit, 'i, 'o) t

  val wait : output:'o -> until:('i -> bool) -> (unit, 'i, 'o) t

  (** An event is a value that will at some point in time (possibly the past, possibly the
      future) transition from "undetermined" to "determined", with some value.  One
      can [wait_for] an event in a computation. *)
  module Event : sig
    type 'a t [@@deriving sexp_of]

    val value : 'a t -> 'a option
  end

  (** [wait_for event ~output] outputs [output] until the step at which [event] becomes
      determined, at which point the [wait_for] proceeds. *)
  val wait_for : 'a Event.t -> output:'o -> ('a, _, 'o) t

  module Component_finished : sig
    type ('a, 'o) t =
      { output : 'o
      ; result : 'a
      }
    [@@deriving sexp_of]
  end

  (** [spawn] creates a child computation that runs [start].  [spawn] returns on the
      current step, and the child starts on the next step.  The parent computation uses
      [child_input] to adjust its input into the form that the child computation sees,
      and [include_child_output] to incorporate the child's output into its output.

      When [update_children_after_finish], unfinished tasks spawned from within [start]
      will be executed even after [start] completes.
  *)
  val spawn
    :  ?update_children_after_finish:bool (** default is [false] *)
    -> Source_code_position.t
    -> start:('i_c -> (('a, 'o_c) Component_finished.t, 'i_c, 'o_c) t)
    -> input:'i_c Data.t
    -> output:'o_c Data.t
    -> child_input:(parent:'i -> 'i_c)
    -> include_child_output:(parent:'o -> child:'o_c -> 'o)
    -> (('a, 'o_c) Component_finished.t Event.t, 'i, 'o) t

  (** [create_component] creates a [Component.t] that runs the computation described
      by [start]. When [update_children_after_finish] is set to true, all component's
      children will be updated even after the child terminates. This will result in
      tasks spawned from within the child task to execute even after the child
      terminates.
  *)
  val create_component
    :  created_at:Source_code_position.t
    -> update_children_after_finish:bool
    -> start:('i -> (('a, 'o) Component_finished.t, 'i, 'o) t)
    -> input:'i Data.t
    -> output:'o Data.t
    -> ('i, 'o) Component.t * ('a, 'o) Component_finished.t Event.t
end
OCaml

Innovation. Community. Security.