Skip to content
This repository has been archived by the owner on Jun 12, 2024. It is now read-only.

Latest commit

 

History

History
142 lines (110 loc) · 4.41 KB

framework.org

File metadata and controls

142 lines (110 loc) · 4.41 KB

System Implementation in Elm

Introduction

System definition

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.

Elm

  • 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.

Define Model Type

A Model is the set of states in the system. This corresponds to $X$ in the sextuple $(X, X0, U, →, Y, H)$ that defines a system.

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.

Initialize the Model

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)
  }

Define Message Type

Messaging is a mechanism to give inputs to the system at runtime. This corresponds to $U$ in the system definition. Every message has a name, and may or may not have data associated with it, depending the definition of the message type.

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.

Implement Update Function

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 $→$, in the system definition.

update : Msg -> Model -> Model
update msg model =
    let {array, selections} = model
    in
        case msg of
            Select i ->
                select i selections
            Swap ->
                swap array selections

Testing

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.

Implement View Functions

So, we have $X$, $X0$, $U$, $→$ and $Y = X$. Only thing remaining is $H$: The output map. The output map is defined by the view function.

view : Model -> Html Msg
view model =
    Html.div [] [viewArray model.array model.selections]