aboutsummaryrefslogtreecommitdiff
path: root/lib/application/application.ml
blob: 422aa4fb8c61d5a9c36588e6dfb7c648347fda97 (plain)
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
(** The Make module build the main application loop.contents

    The function [run] update the state on each event, and return a new state.
    Each event must follow the [event] type, which is composed from the type
    [t], and a module with a fonction [update].

    This example create an application with the state containing a simple
    counter. An even which increment this counter is created and can be used to
    update the state.


    [
        type state = { value : int }

        (** Increment the state. *)
        module Incr = struct
            type t = unit

            let update () state = { value = state.value + 1 }
        end

        (** Decrement the state. *)
        module Incr = struct
            type t = unit

            let update () state = { value = state.value - 1 }
        end

        module App = Make(struct type t = state end)

        (* Create the events *)
        let incr_event = App.E ((), (module Incr:App.Event with type t = Incr.t))
        let decr_event = App.E ((), (module Decr:App.Event with type t = Decr.t))

        let init = { value = 0 } in

        (* Run the main loop *)
        let state = App.run
          init
          (E.select
            [ incr_event
            ; decr_event ] ) in …
    ]

*)
module Make(S:sig type t end) = struct
  module type Event = sig

    type t

    val process: t -> S.t -> S.t

  end

  type event = E : 'a * (module Event with type t = 'a) -> event

  (** Simple helper for the main event loop *)
  let run
    : ?eq:(S.t -> S.t -> bool) -> S.t -> event Note.E.t -> S.t Note.S.t
    = fun ?eq init event ->
      let action = Note.E.map (fun (E (t, (module Event))) st -> Event.process t st) event in
      Note.S.accum ?eq init action

  let dispatch
   : (module Event with type t = 's) -> 's -> event
   = fun (type s) (module M: Event with type t = s) v ->
      E
        ( v
        , (module M : Event with type t = M.t ))

end