diff options
Diffstat (limited to 'stdlib/source/library/lux/control/concurrency/behavioral.lux')
-rw-r--r-- | stdlib/source/library/lux/control/concurrency/behavioral.lux | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/stdlib/source/library/lux/control/concurrency/behavioral.lux b/stdlib/source/library/lux/control/concurrency/behavioral.lux new file mode 100644 index 000000000..1865558aa --- /dev/null +++ b/stdlib/source/library/lux/control/concurrency/behavioral.lux @@ -0,0 +1,50 @@ +(.require + [library + [lux (.except)]] + [// + ["[0]" async (.only Async) (.use "[1]#[0]" monad)] + ["[0]" frp (.only Channel)]]) + +(def <Event> + (template (_ Constructor data) + [[(Constructor data) data]])) + +(type .public (Constructor data) + (-> data (<Event> Constructor data))) + +(type .public Event + (Ex (_ data) + (<Event> Constructor data))) + +(def .public (event constructor) + (All (_ data) + (-> (-> data data) + (Constructor data))) + (exec + [] ... This was added to avoid having auto-currying to fuse the "event" and "self" functions. + ... Otherwise, the "same?" comparison done later would fail. + (function (self data) + [self (constructor data)]))) + +(def .public (event? expected it) + (All (_ data) + (-> (Constructor data) Event + (Maybe data))) + (let [[actual data] it] + (if (same? expected actual) + {.#Some (as_expected data)} + {.#None}))) + +(def .public (scenario events expected initial behavior) + (All (_ state data) + (-> (Channel Event) (Constructor data) state (-> data state (Async state)) + (Async state))) + (frp.mix (function (_ event state) + (when (event? expected event) + {.#Some data} + (behavior data state) + + {.#None} + (async#in state))) + initial + events)) |