package bonsai
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=1d68aab713659951eba5b85f21d6f9382e0efa8579a02c3be65d9071c6e86303
doc/bonsai.extra/Bonsai_extra/index.html
Module Bonsai_extra
Source
val with_inject_fixed_point :
(('action -> unit Bonsai.For_open.Effect.t) Bonsai.For_open.Value.t ->
('result * ('action -> unit Bonsai.For_open.Effect.t))
Bonsai.For_open.Computation.t) ->
'result Bonsai.For_open.Computation.t
with_inject_fixed_point
allows an injection function produced as the result of a computation to be used as the input of that same combination. This "tie-the-knot" operation is legal because actions are scheduled independently of computation evaluation, allowing us to break what seems like a dependency loop.
However, it is important that the input injection function isn't the same one that is returned by the computation (or even a component of the returned injection function). If that happens, an action being triggered will cause an inifinite loop to occur in the aciton scheduler.
val with_self_effect :
(module Bonsai.Model with type t = 'a) ->
f:
('a Bonsai.Computation_status.t Bonsai.For_open.Effect.t
Bonsai.For_open.Value.t ->
'a Bonsai.For_open.Computation.t) ->
'a Bonsai.For_open.Computation.t
with_self_effect
gives access to an effect which produces the output 'a
within the body of f
. This can be useful if you'd like to install an effect handling function on f
whose logic depends on its current value.
val pipe :
(module Bonsai.Model with type t = 'a) ->
(('a -> unit Bonsai.For_open.Effect.t) * 'a Bonsai.For_open.Effect.t)
Bonsai.For_open.Computation.t
pipe
constructs a pipe of a
and returns a pair containing an injection function that enqueues items and an Effect that dequeues them.
val exactly_once :
unit Bonsai.For_open.Effect.t Bonsai.For_open.Value.t ->
unit Bonsai.For_open.Computation.t
As its name implies, exactly_once
runs the event passed in via Value.t
exactly once.
val exactly_once_with_value :
(module Bonsai.Model with type t = 'a) ->
'a Bonsai.For_open.Effect.t Bonsai.For_open.Value.t ->
'a option Bonsai.For_open.Computation.t
As its name implies, exactly_once
runs the event passed in via Value.t
exactly once. The return value is stored and returned. None
is returned while the effect is executing.
val value_with_override :
(module Bonsai.Model with type t = 'a) ->
'a Bonsai.For_open.Value.t ->
('a * ('a -> unit Bonsai.For_open.Effect.t)) Bonsai.For_open.Computation.t
Extends a Value.t by providing a setter effect that can be used to override the returned value. The computation will initially evaluate to the input Value.t
. Once the returned overriding effect is dispatched at least once, the computation will evaluate to the override value provided. The effect can be scheduled more than once to update the override. Use with Bonsai.with_model_resetter
in order to revert the override.
val state_machine0_dynamic_model :
(module Bonsai.Model with type t = 'model) ->
(module Bonsai.Action with type t = 'action) ->
model:
[< `Computed of ('model option -> 'model) Bonsai.For_open.Value.t
| `Given of 'model Bonsai.For_open.Value.t ] ->
apply_action:
(inject:('action -> unit Bonsai.For_open.Effect.t) ->
schedule_event:(unit Bonsai.For_open.Effect.t -> unit) ->
'model ->
'action ->
'model) ->
('model * ('action -> unit Bonsai.For_open.Effect.t))
Bonsai.For_open.Computation.t
This function is identical to Bonsai.state_machine0
except that the default_model
is initially unset, but can be computed or defaulted to a dynamic value.
This means that before an apply_action occurs, the model can change out from underneath the state machine as the default_model value changes. If this is undesirable, you may want to freeze
the default_model first.
val state_machine1_dynamic_model :
(module Bonsai.Model with type t = 'model) ->
(module Bonsai.Action with type t = 'action) ->
model:
[< `Computed of ('model option -> 'model) Bonsai.For_open.Value.t
| `Given of 'model Bonsai.For_open.Value.t ] ->
apply_action:
(inject:('action -> unit Bonsai.For_open.Effect.t) ->
schedule_event:(unit Bonsai.For_open.Effect.t -> unit) ->
'input ->
'model ->
'action ->
'model) ->
'input Bonsai.For_open.Value.t ->
('model * ('action -> unit Bonsai.For_open.Effect.t))
Bonsai.For_open.Computation.t
Read the docs for state_machine0_dynamic_model
. This one has an extra 'input
value that can be taken into account when the apply_action
is invoked.
val state_dynamic_model :
(module Bonsai.Model with type t = 'model) ->
model:
[< `Computed of ('model option -> 'model) Bonsai.For_open.Value.t
| `Given of 'model Bonsai.For_open.Value.t ] ->
('model * ('model -> unit Bonsai.For_open.Effect.t))
Bonsai.For_open.Computation.t
The analog of Bonsai.state
, but with a dynamic model. Read the docs for state_machine0_dynamic_model
Id_gen builds a component which generates unique identifiers by starting at 0 and incrementing by one every time that the effect is called.
val mirror :
(module Bonsai.Model with type t = 'm) ->
store_set:('m -> unit Bonsai.For_open.Effect.t) Bonsai.For_open.Value.t ->
store_value:'m Bonsai.For_open.Value.t ->
interactive_set:('m -> unit Bonsai.For_open.Effect.t) Bonsai.For_open.Value.t ->
interactive_value:'m Bonsai.For_open.Value.t ->
unit Bonsai.For_open.Computation.t
mirror
is used to reflect state back and forth between locations. Frequently this will be used to back up a components model in a more persistent form of storage, such as the URL, or local-storage.
The gist of this combinator is that if you have two states that you'd like to be synchronized, you can feed the "current value" and "set value" functions for both states into mirror
and they'll automatically be kept up to date. Either of these can be backed by any kind of structure, but there are some important differences in their symmetry.
When the component is first loaded, store
has priority, so if the values are different, store
wins, and interactive
has its value "set". From that point on, if either incoming value changes, the opposite setter is called. In the case that both store
and interactive
change at the same time, the tie is broken in favor of interactive
, and store_set
is called.
val mirror' :
(module Bonsai.Model with type t = 'm) ->
store_set:('m -> unit Bonsai.For_open.Effect.t) Bonsai.For_open.Value.t ->
store_value:'m option Bonsai.For_open.Value.t ->
interactive_set:('m -> unit Bonsai.For_open.Effect.t) Bonsai.For_open.Value.t ->
interactive_value:'m option Bonsai.For_open.Value.t ->
unit Bonsai.For_open.Computation.t
mirror'
is like mirror
, but the incoming values have the type 'a option Value.t
instead of just 'a Value.t
. When a value is changed and its new value is None, we don't propagate it to the other setter.
val with_last_modified_time :
equal:('a -> 'a -> bool) ->
'a Bonsai.For_open.Value.t ->
('a * Core.Time_ns.t) Bonsai.For_open.Computation.t
with_last_modified_time
applies a cutoff to the input value and takes a note of the last time the value did not cutoff (in other words, the last time it was changed).
Whenever the returned computation is activated, the "last time modified" value will be reset to the current time.
val is_stable :
equal:('a -> 'a -> bool) ->
'a Bonsai.For_open.Value.t ->
time_to_stable:Core.Time_ns.Span.t ->
bool Bonsai.For_open.Computation.t
is_stable
indicates whether the input value has changed (according to equal
) in the past specified time span.
val value_stability :
(module Bonsai.Model with type t = 'a) ->
'a Bonsai.For_open.Value.t ->
time_to_stable:Core.Time_ns.Span.t ->
'a Stability.t Bonsai.For_open.Computation.t
value_stability
determines whether the current value has changed recently, and also keeps track of the most recent stable value.