bright

Types

Bright holds a state — raw data — and computed data, and is used to compute caching. Bright is instanciated using init, with initial state and computed data.

pub opaque type Bright(state, computed)

Values

pub fn compute(
  bright: #(Bright(a, b), Effect(c)),
  compute_: fn(a, b) -> b,
) -> #(Bright(a, b), Effect(c))

Derives data from the data state, and potentially the current computed state. compute will run at every render, so be careful with computations as they can block paint or actors.

pub fn update(model: Bright(state, computed), msg: Msg) {
  use model <- bright.start(model)
  model
  |> bright.update(update_state(_, msg))
  |> bright.compute(fn (d, c) { Computed(..c, field1: computation1(d)) })
  |> bright.compute(fn (d, c) { Computed(..c, field2: computation2(d)) })
  |> bright.compute(fn (d, c) { Computed(..c, field3: computation3(d)) })
}
pub fn computed(bright: Bright(a, b)) -> b

Extracts computed state from Bright.

pub fn view(model: Bright(state, computed)) {
  let computed = bright.computed(model)
  html.div([], [
    // Use computed here.
  ])
}
pub fn init(state state: a, computed computed: b) -> Bright(a, b)

Creates the initial Bright. state & computed should be initialised with their correct empty initial state.

pub fn lazy_compute(
  bright: #(Bright(a, b), Effect(c)),
  selector: fn(a) -> d,
  compute_: fn(a, b, d) -> b,
) -> #(Bright(a, b), Effect(c))

Derives data like compute lazily. lazy_compute accepts a selector as second argument. Each time the selector returns a different data than previous run, the computation will run. Otherwise, nothing happens. The computation function will receive state, computed and the selected data (i.e. the result from your selector function), in case accessing the selected data is needed.

pub fn update(model: Bright(state, computed), msg: Msg) {
  use model <- bright.start(model)
  model
  |> bright.update(update_state(_, msg))
  // Here, selected is always the result state.field / 10 (the result from selector).
  |> bright.lazy_compute(selector, fn (d, c, selected) { Computed(..c, field1: computation1(d, selected)) })
  |> bright.lazy_compute(selector, fn (d, c, selected) { Computed(..c, field2: computation2(d, selected)) })
  |> bright.lazy_compute(selector, fn (d, c, selected) { Computed(..c, field3: computation3(d, selected)) })
}

/// Use it with lazy_compute to recompute only when the field when
/// { old_state.field / 10 } != { state.field / 10 }
fn selector(d, _) {
  d.field / 10
}
pub fn lazy_schedule(
  bright: #(Bright(a, b), Effect(c)),
  selector: fn(a) -> d,
  schedule_: fn(a, b, d) -> Effect(c),
) -> #(Bright(a, b), Effect(c))

Plugs in existing state like schedule lazily. lazy_schedule accepts a selector as second argument. Each time the selector returns a different data than previous run, the computation will run. Otherwise, nothing happens. The scheduling function will receive state, computed and the selected data (i.e. the result from your selector function), in case accessing the selected data is needed.

pub fn update(model: Bright(state, computed), msg: Msg) {
  use model <- bright.start(model)
  model
  |> bright.update(update_state(_, msg))
  // selected is equal to state.field / 10 (the result from selector).
  |> bright.lazy_schedule(selector, fn (state, computed, selected) {
    use dispatch <- effect.from
    case selected == 10 {
      True -> dispatch(my_msg)
      False -> Nil
    }
  })
}

/// Use it with lazy_schedule to recompute only when the field when
/// { old_state.field / 10 } != { state.field / 10 }
fn selector(state, _) {
  state.field / 10
}
pub fn schedule(
  bright: #(Bright(a, b), Effect(c)),
  schedule_: fn(a, b) -> Effect(c),
) -> #(Bright(a, b), Effect(c))

Plugs in existing state and computed state, to issue some side-effects, when your application needs to run side-effects depending on the current state.

pub fn update(model: Bright(state, computed), msg: Msg) {
  use model <- bright.start(model)
  model
  |> bright.update(update_state(_, msg))
  |> bright.schedule(model, fn (state, computed) {
    use dispatch <- effect.from
    case state.field == 10 {
      True -> dispatch(my_msg)
      False -> Nil
    }
  })
}
pub fn start(
  bright: Bright(a, b),
  next: fn(#(Bright(a, b), Effect(c))) ->
    #(Bright(a, b), Effect(c)),
) -> #(Bright(a, b), Effect(c))

Start the Bright update cycle. Use it as a way to trigger the start of Bright computations, and chain them with other bright calls. start handles all of the hard work, of turning a Bright(state, computed) into a #(Bright(state, computed), Effect(msg)), and will take care that your Bright(state, computed) is always consistent over multiple update cycles.

pub fn update(model: Bright(state, computed), msg: Msg) {
  // Starts the update cycle, and returns #(Bright(state, computed), Effect(msg)).
  use model <- bright.start(model)
  bright.update(model, update_state(_, msg))
}
pub fn state(bright: Bright(a, b)) -> a

Extracts state state from Bright.

pub fn view(model: Bright(state, computed)) {
  let state = bright.state(model)
  html.div([], [
    // Use state here.
  ])
}
pub fn step(
  bright: #(Bright(a, b), Effect(c)),
  next: fn(Bright(a, b)) -> #(d, Effect(c)),
) -> #(d, Effect(c))

Allows to run multiple update on multiple Bright in the same update cycle. Every call to step with compute a new Bright, and will let you chain the steps.

pub type Model {
  Model(
    fst_bright: Bright(state, computed),
    snd_bright: Bright(state, computed),
  )
}

fn update(model: Model, msg: Msg) {
  use fst_bright <- bright.step(update_fst(model.fst_bright, msg))
  use snd_bright <- bright.step(update_snd(model.snd_bright, msg))
  #(Model(fst_bright:, snd_bright:), effect.none())
}
pub fn unwrap(bright: Bright(a, b)) -> #(a, b)

Deprecated: Use `bright.state` and `bright.computed` instead.

Extracts state & computed states from Bright.

pub fn view(model: Bright(state, computed)) {
  let #(state, computed) = bright.unwrap(model)
  html.div([], [
    // Use state or computed here.
  ])
}
pub fn update(
  bright: #(Bright(a, b), Effect(c)),
  update_: fn(a) -> #(a, Effect(c)),
) -> #(Bright(a, b), Effect(c))

Update state & effects during update cycle. Use it a way to update your state stored in Bright, and chain them with other bright calls.

pub fn update(model: Bright(state, computed), msg: Msg) {
  use model <- bright.start(model)
  // Run an update, and returns #(Bright(state, computed), Effect(msg)).
  bright.update(model, update_state(_, msg))
}
Search Document