From 8c569e5d33eddfd3972302c89c832fd01a4e0aa9 Mon Sep 17 00:00:00 2001 From: Vladimir Ciobanu Date: Tue, 29 Sep 2020 00:58:32 +0300 Subject: [PATCH 1/3] README.md: Add quick start section --- README.md | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 470c7ad..ec6edff 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,55 @@ spago install machines ## Quick start -The quick start hasn't been written yet. Contributions are welcome! +The examples here use `Identity` for simplicity. Usually, you would use +a different `Monad`, such as `Effect`, `Aff`, `State`, etc. + +There are several ways to build machines. One way is to use `do` syntax, +for example: + +```purescript +machine1 :: MealyT Identity Unit String +machine1 = do + number <- fromArray [10, 20, 30, 40, 50, 0, 60, 70] + scaled <- + if number == 0 + then halt + else pure $ 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 intoa string. + +The resulting machine can be materialized via `toUnfoldable unit machine1 :: Array String`. The result is `["5","10","15","20","25"]`. + +Another way to write the same machine is using machine composition: + +```purescript +machine2 :: MealyT Identity Unit String +machine2 = + fromArray [10, 20, 30, 40, 50, 0, 60, 70] + >>> pureMealy haltOn0 + >>> pureMealy scale + >>> pureMealy pretty + where + haltOn0 0 = Halt + haltOn0 n = Emit n $ pureMealy haltOn0 + + scale n = Emit (n `div` 2) $ pureMealy scale + + 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 From 8ce56f49da0046e5959b48cc57ffd1bdc2daf7da Mon Sep 17 00:00:00 2001 From: Vladimir Ciobanu Date: Tue, 29 Sep 2020 01:03:16 +0300 Subject: [PATCH 2/3] README.md: Add type signatures to a few helpers for clarity. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ec6edff..faf8492 100644 --- a/README.md +++ b/README.md @@ -53,11 +53,14 @@ machine2 = >>> 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 ``` From 32d1192f553d01d948fdc856a3c68bd9b868d45e Mon Sep 17 00:00:00 2001 From: Vladimir Ciobanu Date: Wed, 30 Sep 2020 02:16:25 +0300 Subject: [PATCH 3/3] Addressed review comments. --- README.md | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index faf8492..552eabc 100644 --- a/README.md +++ b/README.md @@ -20,32 +20,47 @@ spago install machines ## Quick start -The examples here use `Identity` for simplicity. Usually, you would use -a different `Monad`, such as `Effect`, `Aff`, `State`, etc. +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] - scaled <- - if number == 0 - then halt - else pure $ div number 2 + 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 intoa string. +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"] +``` -The resulting machine can be materialized via `toUnfoldable unit machine1 :: Array String`. The result is `["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. -Another way to write the same machine is using machine composition: +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]