Capucine Example: Subject-Observer PatternA possible implementation of the classic OO Subject-Observer Pattern. |
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
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)