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.
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
There are several ways to build machines. One way is to use
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 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 a
MealyT Identity Unit Intwhich generates the integerers in the provided array,
pureMealy haltOn0is a
MealyT Int Intwhich halts on 0,
pureMealy scaleis a
MealyT Int Intwhich scales the inputs, and
pureMealy prettyis a
MealyT Int Stringwhich 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.
- Search or start a thread on the PureScript Discourse if you have general questions. You can also ask questions in the
#purescript-beginnerschannels on the Functional Programming Slack (invite link).
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.