A library for building type-safe state machines.
Table of Contents
- State Transitions are specified with type level DSL.
- Compile time guarantees that state update functions are complete and valid.
- Automatic state diagram generation
- State machine graph analysis
- Optimized for speed
(once published to package set:)
spago install transitFull source code: test/Examples/CountDown.purs
Let's consider a simple count down state machine which is described by the following state diagram:
To implement this state machine with Transit first we need to define the state and message types as Variants:
type State = Variant
( "Idle" :: {}
, "Counting" :: { count :: Int }
, "Done" :: {}
)
type Msg = Variant
( "Start" :: { initialCount :: Int }
, "Tick" :: {}
, "Reset" :: {}
)Then we need to define the state machine transitions as follows. Note that the last transition has 2 possible return states.
type CountDownTransit =
Transit
:* ("Idle" :@ "Start" >| "Counting")
:* ("Done" :@ "Reset" >| "Idle")
:*
( "Counting" :@ "Tick"
>| "Counting"
>| "Done"
)Finally, we write the update function that is checked at compile against the state machine specification:
update :: State -> Msg -> State
update = mkUpdate @CountDownTransit
( match @"Idle" @"Start" \_ msg ->
return @"Counting" { count: msg.initialCount }
)
( match @"Done" @"Reset" \_ _ ->
return @"Idle"
)
( match @"Counting" @"Tick" \state _ ->
let
nextCount = state.count - 1
in
if nextCount == 0 then
return @"Done"
else
return @"Counting" { count: nextCount }
)Reflect type level state machine specification to a term level representation:
countDownTransit :: TransitCore
countDownTransit = reflectType (Proxy @CountDownTransit)Generate state diagram or perform other analysis on the state machine's runtime representation:
main :: Effect Unit
main = do
let
graph :: String
graph = TransitGraphviz.generate_ countDownTransit
FS.writeTextFile UTF8 "renders/count-down.dot" graph