Machines is a library for building finite state machines. Finite state machines are useful for modeling many concerns that developers face. They help you describe a set of possible states and rules for how to transition from one state to another. The result is a complete view of possible states and transitions between states.
Currently this library implements Mealy machines with halting.
Install machines
with Spago:
spago install machines
Mealy machines are finite state machines. The MealyT f i o
type represents a machine where f
is the effect used for evaluation, i
is the input, and o
is the output value. The examples here use Identity
as the effect type for simplicity, but you would usually use a different Monad
such as Effect
, Aff
, or State
.
There are several ways to build machines. One way is to use do
syntax,
for example:
import Prelude
import Control.MonadZero (guard)
import Data.Machine.Mealy (MealyT, fromArray, toUnfoldable)
import Data.Identity (Identity)
machine1 :: MealyT Identity Unit String
machine1 = do
number <- fromArray [10, 20, 30, 40, 50, 0, 60, 70]
guard (number /= 0)
let scaled = div number 2
pure $ show scaled
This will create a machine machine1
which goes through the "inputs"
from the array. It then checks and halts on any zero input, and otherwise
scales the inputs (by dividing by 2). The result is then transformed into a string.
The resulting machine can be materialized via
> toUnfoldable unit machine1 :: Array String
["5","10","15","20","25"]
Another way to write the same machine is using machine composition. In this example, we will be creating multiple machines using pureMealy
, which relies on Step
s.
A Step f i o
represents a state transition in the machine. When you run a machine you are executing a series of steps. At each step the machine can stop via the Halt
constructor or Emit
a value and construct the rest of the machine.
import Prelude
import Data.Identity (Identity)
import Data.Machine.Mealy (MealyT, Step(..), fromArray, pureMealy)
machine2 :: MealyT Identity Unit String
machine2 =
fromArray [10, 20, 30, 40, 50, 0, 60, 70]
>>> pureMealy haltOn0
>>> pureMealy scale
>>> pureMealy pretty
where
haltOn0 :: Int -> Step Identity Int Int
haltOn0 0 = Halt
haltOn0 n = Emit n $ pureMealy haltOn0
scale :: Int -> Step Identity Int Int
scale n = Emit (n `div` 2) $ pureMealy scale
pretty :: Int -> Step Identity Int String
pretty n = Emit (show n) $ pureMealy pretty
This machine does the same thing, except it creates multiple machines:
fromArray [10, 20 ...
is aMealyT Identity Unit Int
which generates the integerers in the provided array,pureMealy haltOn0
is aMealyT Int Int
which halts on 0,pureMealy scale
is aMealyT Int Int
which scales the inputs, andpureMealy pretty
is aMealyT Int String
which converts inputs from integers to strings.
machines
documentation is stored in a few places:
- Module documentation is published on Pursuit.
- Written documentation is kept in the docs directory.
- Usage examples can be found in the test suite.
If you get stuck, there are several ways to get help:
- Open an issue if you have encountered a bug or problem.
- Ask general questions on the PureScript Discourse forum or the PureScript Discord chat.
You can contribute to machines
in several ways:
-
If you encounter a problem or have a question, please open an issue. We'll do our best to work with you to resolve or answer it.
-
If you would like to contribute code, tests, or documentation, please read the contributor guide. It's a short, helpful introduction to contributing to this library, including development instructions.
-
If you have written a library, tutorial, guide, or other resource based on this package, please share it on the PureScript Discourse! Writing libraries and learning resources are a great way to help this library succeed.