Capucine Example: Subject-Observer Pattern

A possible implementation of the classic OO Subject-Observer Pattern.

Back to Capucine

Discussion

This is one possible implementation of the Subject-Observer Pattern, which is well-known amongst programmers of object-oriented languages. This example also features an implementation of chained lists. To compile it, go into the capucine directory and type:

ocamlbuild bench/sparse.gwhy

Code

class Node (a) {R} =
  unit | (a * Node (a) {R} [R])
end

val nil(): Node (a) {R} [R]
  consumes R^e
  produces R^c =
    let n = new Node (a) {R} in
    n := Left ();
    n

val cons(x: a, l: Node (a) {R} [R]): unit
  consumes R^g
  produces R^g =
    let n = new Node (a) {R} in
    n := !l;
    (focus l) := Right (x, n)

class Observer(Subject) = (Subject * int) end

class Subject{Rsub} =
  own Rlist, Robs;
  (Node(Observer(Subject{Rsub}[Rsub])[Robs]){Rlist}[Rlist] * int)
end

val notify(this: Observer(Subject{Rsub}[Rsub])[Robs], v: int): unit
  consumes Robs^g
  produces Robs^g =
    let o = focus this in
    o := (!o.1, v)

val register(
  this: Subject{Rsub}[Rsub],
  o: Observer(Subject{Rsub}[Rsub])[Ro]): unit
  consumes Rsub^c, Ro^c
  produces Rsub^c =
    let o = adopt o as Rsub.Robs in
    cons(o, (!this).1);
    notify(o, !this.2)

val foreach_notify(
  l: Node(Observer(Subject{Rsub}[Rsub])[Robs]){Rl}[Rl],
  n: int): unit
  consumes Rl^g
  produces Rl^g
    (* need pattern matching (not implemented in Capucine yet) *)

val update(this: Subject{Rsub}[Rsub], n: int): unit
  consumes Rsub^c
  produces Rsub^c =
    this := (!this.1, n);
    foreach_notify(!this.1, n)