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:
- 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)
- 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!