module S:`sig`

..`end`

Signal combinators.

Consult their semantics.

type`'a`

t =`'a React.signal`

The type for signals of type

`'a`

.`val const : ``'a -> 'a React.signal`

`const v`

is always `v`

, [`const v`

]`= v`

.`val create : ``?eq:('a -> 'a -> bool) ->`

'a -> 'a React.signal * (?step:React.step -> 'a -> unit)

`create i`

is a primitive signal `s`

set to `i`

and a
`set`

function. The function `set`

is such that:
`set v`

sets the signal's value to`v`

at the time it is called and triggers an update step.`set ~step v`

sets the signal's value to`v`

at the time it is called and updates it dependencies when`step`

is executed`set ~step v`

raises`Invalid_argument`

if it was previously called with a step and this step has not executed yet or if the given`step`

was already executed.

`set`

must not be executed inside an update step.`val value : ``'a React.signal -> 'a`

`value s`

is `s`

's current value.
**Warning.** If executed in an update
step may return a non up-to-date value or raise `Failure`

if
the signal is not yet initialized.

`val retain : ``'a React.signal -> (unit -> unit) -> [ `R of unit -> unit ]`

`retain s c`

keeps a reference to the closure `c`

in `s`

and
returns the previously retained value. `c`

will
**Raises.** `Invalid_argument`

on constant signals.

`val stop : ``?strong:bool -> 'a React.signal -> unit`

`stop s`

, stops updating `s`

. It conceptually becomes `React.S.const`

with the signal's last value and cannot be restarted. Allows to
disable effectful signals.
The `strong`

argument should only be used on platforms
where weak arrays have a strong semantics (i.e. JavaScript).
See details.

**Note.** If executed in an update step the signal may
still update in the step.

`val equal : ``?eq:('a -> 'a -> bool) -> 'a React.signal -> 'a React.signal -> bool`

`equal s s'`

is `true`

iff `s`

and `s'`

are equal. If both
signals are `React.S.const`

ant `eq`

is used between their value
(defauts to structural equality). If both signals are not
`React.S.const`

ant, physical equality is used.`val trace : ``?iff:bool t -> ('a -> unit) -> 'a React.signal -> 'a React.signal`

`trace iff tr s`

is `s`

except `tr`

is invoked with `s`

's
current value and on `s`

changes when `iff`

is `true`

(defaults
to `S.const true`

). For all t where [`s`

]`= v`

and (t = 0
or ([`s`

]`= v'`

and `eq v v' = false`

)) and
[`iff`

]`true`

, `tr`

is invoked with `v`

.`val hold : ``?eq:('a -> 'a -> bool) -> 'a -> 'a React.event -> 'a React.signal`

`hold i e`

has the value of `e`

's last occurrence or `i`

if there
wasn't any.
- [
`hold i e`

]_{t}`= i`

if [`e`

]_{<=t}`= None`

- [
`hold i e`

]_{t}`= v`

if [`e`

]_{<=t}`= Some v`

`val app : ``?eq:('b -> 'b -> bool) ->`

('a -> 'b) React.signal -> 'a React.signal -> 'b React.signal

`app sf s`

holds the value of `sf`

applied
to the value of `s`

, [`app sf s`

]`=`

[`sf`

]`s`

]`val map : ``?eq:('b -> 'b -> bool) -> ('a -> 'b) -> 'a React.signal -> 'b React.signal`

`map f s`

is `s`

transformed by `f`

, [`map f s`

]`f`

[`s`

]`val filter : ``?eq:('a -> 'a -> bool) ->`

('a -> bool) -> 'a -> 'a React.signal -> 'a React.signal

`filter f i s`

is `s`

's values that satisfy `p`

. If a value does not
satisfy `p`

it holds the last value that was satisfied or `i`

if
there is none.
- [
`filter p s`

]_{t}`=`

[`s`

]_{t}if`p`

[`s`

]_{t}`= true`

. - [
`filter p s`

]_{t}`=`

[`s`

]_{t'}if`p`

[`s`

]_{t}`= false`

and t' is the greatest t' < t with`p`

[`s`

]_{t'}`= true`

. - [
`filter p e`

]_{t}`= i`

otherwise.

`val fmap : ``?eq:('b -> 'b -> bool) ->`

('a -> 'b option) -> 'b -> 'a React.signal -> 'b React.signal

`fmap fm i s`

is `s`

filtered and mapped by `fm`

.
- [
`fmap fm i s`

]_{t}`=`

v if`fm`

[`s`

]_{t}`= Some v`

. - [
`fmap fm i s`

]_{t}`=`

[`fmap fm i s`

]_{t'}if`fm`

[`s`

]_{t}`= None`

and t' is the greatest t' < t with`fm`

[`s`

]_{t'}`<> None`

. - [
`fmap fm i s`

]_{t}`= i`

otherwise.

`val diff : ``('a -> 'a -> 'b) -> 'a React.signal -> 'b React.event`

`diff f s`

is an event with occurrences whenever `s`

changes from
`v'`

to `v`

and `eq v v'`

is `false`

(`eq`

is the signal's equality
function). The value of the occurrence is `f v v'`

.
- [
`diff f s`

]_{t}`= Some d`

if [`s`

]_{t}`= v`

and [`s`

]_{t-dt}`= v'`

and`eq v v' = false`

and`f v v' = d`

. - [
`diff f s`

]_{t}`= None`

otherwise.

`val changes : ``'a React.signal -> 'a React.event`

`changes s`

is `diff (fun v _ -> v) s`

.`val sample : ``('b -> 'a -> 'c) -> 'b React.event -> 'a React.signal -> 'c React.event`

`sample f e s`

samples `s`

at `e`

's occurrences.
- [
`sample f e s`

]_{t}`= Some (f ev sv)`

if [`e`

]_{t}`= Some ev`

and [`s`

]_{t}`= sv`

. - [
`sample e s`

]_{t}`= None`

otherwise.

`val on : ``?eq:('a -> 'a -> bool) ->`

bool React.signal -> 'a -> 'a React.signal -> 'a React.signal

`on c i s`

is the signal `s`

whenever `c`

is `true`

.
When `c`

is `false`

it holds the last value `s`

had when
`c`

was the last time `true`

or `i`

if it never was.
- [
`on c i s`

]_{t}`=`

[`s`

]_{t}if [`c`

]_{t}`= true`

- [
`on c i s`

]_{t}`=`

[`s`

]_{t'}if [`c`

]_{t}`= false`

where t' is the greatest t' < t with [`c`

]_{t'}`= true`

. - [
`on c i s`

]_{t}`=`

`i`

otherwise.

`val when_ : ``?eq:('a -> 'a -> bool) ->`

bool React.signal -> 'a -> 'a React.signal -> 'a React.signal

`val dismiss : ``?eq:('a -> 'a -> bool) ->`

'b React.event -> 'a -> 'a React.signal -> 'a React.signal

`dismiss c i s`

is the signal `s`

except changes when `c`

occurs
are ignored. If `c`

occurs initially `i`

is used.
- [
`dismiss c i s`

]_{t}`=`

[`s`

]_{t'}where t' is the greatest t' <= t with [`c`

]_{t'}`= None`

and [`s`

]_{t'-dt}`<>`

[`s`

]_{t'} - [
`dismiss_ c i s`

]_{0}`=`

`v`

where`v = i`

if [`c`

]_{0}`= Some _`

and`v =`

[`s`

]_{0}otherwise.

`val accum : ``?eq:('a -> 'a -> bool) -> ('a -> 'a) React.event -> 'a -> 'a React.signal`

`val fold : ``?eq:('a -> 'a -> bool) ->`

('a -> 'b -> 'a) -> 'a -> 'b React.event -> 'a React.signal

`val merge : ``?eq:('a -> 'a -> bool) ->`

('a -> 'b -> 'a) -> 'a -> 'b React.signal list -> 'a React.signal

`merge f a sl`

merges the value of every signal in `sl`

using `f`

and the accumulator `a`

.
[`merge f a sl`

]_{t}
`= List.fold_left f a (List.map`

[]_{t}` sl)`

.

`val switch : ``?eq:('a -> 'a -> bool) -> 'a React.signal React.signal -> 'a React.signal`

`switch ss`

is the inner signal of `ss`

.
- [
`switch ss`

]_{t}`=`

[[`ss`

]_{t}]_{t}.

`val bind : ``?eq:('b -> 'b -> bool) ->`

'a React.signal -> ('a -> 'b React.signal) -> 'b React.signal

`bind s sf`

is `switch (map ~eq:( == ) sf s)`

.`val fix : ``?eq:('a -> 'a -> bool) ->`

'a -> ('a React.signal -> 'a React.signal * 'b) -> 'b

`fix i sf`

allow to refer to the value a signal had an
infinitesimal amount of time before.
In `fix sf`

, `sf`

is called with a signal `s`

that represents
the signal returned by `sf`

delayed by an infinitesimal amount
time. If `s', r = sf s`

then `r`

is returned by `fix`

and `s`

is such that :

- [
`s`

]_{t}`=`

`i`

for t = 0. - [
`s`

]_{t}`=`

[`s'`

]_{t-dt}otherwise.

`eq`

is the equality used by `s`

.

**Raises.** `Invalid_argument`

if `s'`

is directly a delayed signal (i.e.
a signal given to a fixing function).

**Note.** Regarding values depending on the result `r`

of
`s', r = sf s`

the following two cases need to be distinguished :

- After
`sf s`

is applied,`s'`

does not depend on a value that is in a step and`s`

has no dependents in a step (e.g in the simple case where`fix`

is applied outside a step).In that case if the initial value of

`s'`

differs from`i`

,`s`

and its dependents need to be updated and a special update step will be triggered for this. Values depending on the result`r`

will be created only after this special update step has finished (e.g. they won't see the`i`

of`s`

if`r = s`

). - Otherwise, values depending on
`r`

will be created in the same step as`s`

and`s'`

(e.g. they will see the`i`

of`s`

if`r = s`

).

Lifting combinators. For a given `n`

the semantics is :

[`ln f a1`

... `an`

]_{t} = f [`a1`

]_{t} ... [`an`

]_{t}

`val l1 : ``?eq:('b -> 'b -> bool) -> ('a -> 'b) -> 'a React.signal -> 'b React.signal`

`val l2 : ``?eq:('c -> 'c -> bool) ->`

('a -> 'b -> 'c) -> 'a React.signal -> 'b React.signal -> 'c React.signal

`val l3 : ``?eq:('d -> 'd -> bool) ->`

('a -> 'b -> 'c -> 'd) ->

'a React.signal -> 'b React.signal -> 'c React.signal -> 'd React.signal

`val l4 : ``?eq:('e -> 'e -> bool) ->`

('a -> 'b -> 'c -> 'd -> 'e) ->

'a React.signal ->

'b React.signal -> 'c React.signal -> 'd React.signal -> 'e React.signal

`val l5 : ``?eq:('f -> 'f -> bool) ->`

('a -> 'b -> 'c -> 'd -> 'e -> 'f) ->

'a React.signal ->

'b React.signal ->

'c React.signal -> 'd React.signal -> 'e React.signal -> 'f React.signal

`val l6 : ``?eq:('g -> 'g -> bool) ->`

('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g) ->

'a React.signal ->

'b React.signal ->

'c React.signal ->

'd React.signal -> 'e React.signal -> 'f React.signal -> 'g React.signal

The following modules lift some of

`Pervasives`

functions and
operators.module Bool:`sig`

..`end`

module Int:`sig`

..`end`

module Float:`sig`

..`end`

module Pair:`sig`

..`end`

module Option:`sig`

..`end`

module Compare:`sig`

..`end`

Given an equality function `equal`

and a type `t`

, the functor
`React.S.Make`

automatically applies the `eq`

parameter of the combinators.
The outcome is combinators whose *results* are signals with
values in `t`

.

Basic types are already specialized in the module `React.S.Special`

, open
this module to use them.

module type EqType =`sig`

..`end`

Input signature of

`React.S.Make`

module type S =`sig`

..`end`

Output signature of

`React.S.Make`

module Make:

Functor specializing the combinators for the given signal value type

module Special:`sig`

..`end`

Specialization for booleans, integers and floats.