A system is defined as a sextuple $(X, X0, U, →, Y, H)$.
-
$X$ : Set of states - $X0$: Set of initial states ($X0 ∈ X$)
-
$U$ : Set of inputs to the system -
$→$ : transition relation -
$Y$ : Set of outputs -
$H$ : Output map ($X → Y$ )
To implement a complete system, each of these components need to be well defined and implemented. This document describes the process of implementing each of these components in elm. The result is a module that can be run as an interactive web application.
- Follow the elm guide to learn the core language and the architecture.
- Additional pacakges:
- elm-community/elm-test
- unit testing
- MACASOutreach/GraphicSVG
- for views in SVG
- elm-community/list-extra
- functions for list
- A reference implementation of systems for bubblesort along with test cases can be found here.
A Model
is the set of states in the system. This corresponds
to
Following example shows the model type that contains an array and a custom type.
type Selections
= NoneSelected
| OneSelected Int
| BothSelected Int Int
type alias Model =
{ array : List Int
, selections : Selections
}
There is no single unique way to define a model and your state space depends on the problems as well as the interactions you want to implement in the application.
For example, in the above model, the problem of sorting an array
only requires the array
field. The second field selections
is
added because the user will perform sorting through swap operation,
which requires two integer indices, which will be decided at the
runtime by the user. We, will see that as the interction model
evolves, the system definition also needs to change accordingly.
After defining the set of states in the Model type, you need to give an initial state to the model.
If you define init
as an initialization of the model then $init
∈ X0$.
init =
{ array = [30, 24, 56, 5, 0]
, selections = (BothSelected 0 2)
}
Messaging
is a mechanism to give inputs to the system at runtime.
This corresponds to
Msg = Select Int
| Swap
In the above example, the Msg
type defines two message types:
Select Int
and Swap
. Msg
is an example of a union type.
The first message type Select Int
holds an integer value, which is
passed to systems at runtime. For example, Select 3
is an
instance of the Msg
type. Swap
is also an instance of Msg
type. Swap
does not contain any additional data, but it is itself
a complete message, telling the system to perform a swap operation.
The update function defines the actions corresponding to each of the
message types. These actions are performed at runtime, when the
system receives a message. The update function corresponds to
transition relation
update : Msg -> Model -> Model
update msg model =
let {array, selections} = model
in
case msg of
Select i ->
select i selections
Swap ->
swap array selections
Each of functions used in the update function, should have unit tests to verify the behavior each of the functions.
Look at the reference implementation for details.
So, we have view
function.
view : Model -> Html Msg
view model =
Html.div [] [viewArray model.array model.selections]