Реактивное программирование

type Border =
    inherit Control

    var obs left : u32 = 0
    var obs right : u32 = 0
    var obs up : u32 = 0
    var obs down : u32 = 0
    var obs content : Option<Control> = None

Модификатор obs создаёт контейнер типа mut Atom<T>, поддерживающий публикацию оповещений об изменении значения.

let content_width = content@atom.map { case _ of
    None -> 0
    Some control -> control.width }

content@atom вместо значения поля content возвращает контейнер, на котором определен метод map.

let thickness = (border.left@atom
                 border.right@atom
                 border.up@atom
                 border.down@atom)
                |> to_atom

Можно преобразовать кортеж атомов в атом кортежей, thickness имеет тип Atom<(u32, u32, u32, u32)>.

val memory@atom = (content_width, content_height, thickness)
                  |> to_atom
                  |> map { width, height, thickness ->
                      if width == 0 || height == 0
                      then None
                      else Some (width, height, thickness) }
                  |> option_map { width, height, (left, right, up, down) ->
                      ...
                      MeshMemory.from_quads quads.as_slice }

Из-за модификатора @atom привязка memory имеет тип Option<MeshMemory>, а не Atom<Option<MeshMemory>>.

let obs size : u32 = 10
let obs factor : f32 = 0.8

margin.up@obs = size@obs as f32 * factor@obs |> as<u32>

Поле up объекта margin будет обновлено при изменении значения привязок size и factor.