TyOverby/composition-comparison

More abstract presentation and other ways of composing

stevana opened this issue · 4 comments

Hey,

I'm interested in ways of composing state machines as well, when I read your text two things came to mind:

  1. Have you thought of composition in a more abstract way? For example, if we define state machines to be a function from some input and some state to some new state:
    SM = i -> s -> s

Then we can define your "parallel composition" as:

    _*_ : SM i s -> SM j t -> SM (i + j) (s, t)
     f * _g (Inl i) (s, t) = (f i s, t)
     _f * g (Inr j) (s, t) = (s, g j t)

And your "sequential composition" as perhaps something like:

   _; _ : SM i s -> SM j (s, t) -> SM (i + j) (s, t)
  f; _g (Inl i) (s, t) = (f i s, t)
  _f; g (Inr j) (s, t) = g j (s, t)
  1. Are you familiar with the composition techniques described here and how StateCharts compose?

How does

SM = i -> s -> s

work out? Is i the action doing the transitioning, or an additional input to the transition function?

I think of Bonsai components as being closer to this type signature

type ('input, 'model, 'action, 'result) t

val par 
  :  ('i, 'm1, 'a1, 'r1) t 
  -> ('i, 'm2, 'a2, 'r2) t 
  -> ('i, 'm1 * 'm2, ('a1, 'a2) Either.t, 'r1 * 'r2) t 

val seq
  :  ('i, 'm1, 'a1, 'r1) t 
  -> ('r1, 'm2, 'a2, 'r2) t 
  -> ('i, 'm1 * 'm2, ('a1, 'a2) Either.t, 'r2) t

with some external "runner"

val eval: ('i, 'm, 'a, 'r) t -> 'i -> 'm -> ('r * ('a -> 'm))

Is i the action doing the transitioning, or an additional input to the transition function?

I was thinking of my i being your Action (= Incr | Decr) but also with your by : Int parameter (i.e. Input = Incr Int | Decr Int). Whereas I now see that you separate the two things (your 'action and 'input above)?

In your Bonsai/Elm code examples where is 'result produced? I thought that apply_action/update always produced a new 'model (my s)?

(Thanks for taking the time to distil your ideas into something semantical, the syntax of a foreign language and library made it difficult for me to see exactly what's going on!)

In your Bonsai/Elm code examples where is 'result produced? I thought that apply_action/update always produced a new 'model (my s)?

A bonsai component is really defined in terms of its output. The type I wrote up above (type ('input, 'model, 'action, 'result) t) is mostly a lie; it's really closer to something like this:

type 'a Value.t  
type ('model, 'action, 'result) Computation.t
type ('input, 'model, 'action, 'result) t = 'input Value.t -> ('model, 'action, 'result) Computation.t

But in reality, we type erase the action and model parameters, so it's actually closer to

type 'a Value.t  
type 'a Computation.t
type ('a, 'b) t = 'input Value.t -> 'b Computation.t

You can see the result of the counter component being built here:
https://github.com/TyOverby/composition-comparison/blob/main/shared/counter.ml#L34

In this case, the component is building a view of itself, but also exporting its model so that other components can see what its value is.

Thanks!