Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Quick start section in the README file #38

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,73 @@ spago install machines

## Quick start

The quick start hasn't been written yet. Contributions are welcome!
Mealy machines are finite state machines. The `MealyT f s a` type represents a machine where `f` is the effect used for evaluation, `s` is the input state, and `a` 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:

```purescript
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

```purescript
> 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 s a` 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.

```purescript
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
Comment on lines +71 to +76
Copy link
Contributor

@thomashoneyman thomashoneyman Sep 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For parity with the earlier example, should these two be merged?

    scale :: Int -> Step Identity Int Int
    scale n
      | n == 0 = Halt
      | otherwise = Emit (n `div` 2) $ pureMealy scale

as this is introduced as "the same machine as before".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right! I changed the examples a bit, using guard in the monadic version. Does this look better?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are comfortable switching to two spaces instead of four in the example (as is done in the do example above) I'd appreciate that, but otherwise 👍!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to leave this unmerged to give you a moment to respond to this, but at that point I will go ahead and merge.


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 Int` which generates
the integerers in the provided array,
- `pureMealy haltOn0` is a `MealyT Int Int` which halts on 0,
- `pureMealy scale` is a `MealyT Int Int` which scales the inputs, and
- `pureMealy pretty` is a `MealyT Int String` which converts inputs
from integers to strings.

## Documentation

Expand Down