How to Compose Janestreet/Bonsai components?

First and foremost, I think it’s worth noting that the basic building block of Bonsai is 'a Value.ts and 'a Computation.ts. The main idea behind composing those is simple:

If I want to use a 'a Computation.t, I use let%sub (or another operator), which instantiates a 'a Value.t. There’s a caveat: whatever code I’m now writing is contractually forced to return a 'b Computation.t.

Then, I can use let%arr to define a new 'b Computation.t in terms of a bunch of Value.ts.
That’s all there really is to composition in Bonsai. For some examples comparing to react, see GitHub - TyOverby/composition-comparison

In Bonsai, not every component needs to be defined in terms of Bonsai.state or Bonsai.state_machine0. In fact, most of your components will likely be computations composing other components, or using some other Bonsai utils.

That being said, I wouldn’t think of things as Dog.t, Apple.t, etc. When you define state components with Bonsai, you get a (Model.t, Action.t -> Effect.t) Computation.t. in other words, you get the incremental value of the state computation, and also a function you can use to tell the state to change (in adherence to your rigorously defined rules).

So how do we think about composing this? Well, presumably, you care about the value produced by your building block state machines. So you’ll use let%sub and let%arr to unpack and use those values. Also, since you’re not hardcoding these values, you expect them to change at some point. When might that happen?

  • On user interaction, in which you’d use the inject function in a virtual Dom effect handler
  • On a timer / lifecycle event, in which case you’d also use the inject function for a handler
  • triggered by other computations processing their own actions. In that case, you’d use the schedule_event argument inside that computation’s apply_action. And of course, you’ll need to pass your inject function to that component, either as an input (state_machine1), or as data given to the Action.t.

One of the upsides of Bonsai vs Incr_dom is that you don’t need to worry about these .ts; Bonsai will automatically do that for you behind the scenes on composition.

What you need to think about is what your components produce. If your Widget.t just packages the cat, dog, apple, orange together so they can be used by other computations, that’s fine. If it produces something else completely, such as Vdom.Node.t, that’s fine too.

That’s not necessary at all.

If you’re interested, I’ve finished the first draft of my snake game tutorial. It teaches the creation and composition of state machines. If you have time / interest in test driving it, I would really appreciate any feedback as to structure / format / content: