typed-fsm example: todoList
The overall structure of todoList is similar to elm:
Elm programs always look something like this:
The Elm program produces HTML to show on screen, and then the computer sends back messages of what is going on. “They clicked a button!”
What happens within the Elm program though? It always breaks into three parts:
- Model — the state of your application
- View — a way to turn your state into HTML
- Update — a way to update your state based on messages
Compared with elm, todoList introduces control states, which affect Model, View, Update, and Message at the same time.
Core idea
Let’s take a TodoList:
Each state here represents a page:
Main represents the main page showing the todolist content.
AreYouSure represents the page for selecting Yes or No.
Modify represents the page for modifying a todo.
Add represents the page for adding a todo.
Exit represents exit.
Each arrow represents a message.
You may notice that this looks a lot like fsm. Each state here represents a control flow or a page, and Message changes the control flow or page and may also change the data.
I will use typed-fsm to separate the control state from the all data.
Comparing elm and todoList
elm | todoList |
---|---|
Mode | Control State: ps , Data State: ds |
View | Sing t → ds → UI ps (t :: ps) a |
Update | Op ps ds IO () (to :: ps) (from ps) |
Message | Msg ps (from :: ps) (to :: ps) |
The UI part uses the modified threepenny-gui, the main change is to change the original (UI a) to (UI ps (t::ps) a).
There are at least three advantages to doing this.
-
The type of the View part has a clear control state, which can limit the type of Message and avoid sending error messages.
-
The Update part can give full play to the advantages of typed-fsm, and typed-fsm takes over the entire control flow.
-
Extract the common part and simplify the control state.
At the same time, typed-fsm supports singletons, and the definition of control state is also very easy:
$( singletons
[d|
data Todo
= Main
| Add
| Delete
| Modify
| Exit
| Action Todo Todo
| AreYouSure Todo Todo
deriving (Show, Eq, Ord)
|]
)