Module

Data.Machine.Mealy

This module provides the building blocks required to create finite state machines.

#MealyT

newtype MealyT f i o

Mealy is a finite state machine, where:

  • f is the effect under which we evaluate,
  • i is the input type and
  • o is the output type.

Instances

#runMealyT

runMealyT :: forall f i o. MealyT f i o -> i -> f (Step f i o)

#hoistMealyT

hoistMealyT :: forall f g i. Functor g => (f ~> g) -> (MealyT f i) ~> (MealyT g i)

Transforms a Mealy machine running in the context of f into one running in g, given a natural transformation from f to g.

#Step

data Step f i o

Step is the core for running machines. Machines can either stop via the Halt constructor, or emit a value and recursively construct the rest of the machine.

Constructors

#Source

type Source f o = MealyT f Unit o

Sources are 'initial nodes' in machines. They allow for data to be generated.

#Sink

type Sink f i = MealyT f i Unit

Sinks are 'terminator nodes' in machines. They allow for an effectful computation to be executed on the inputs.

#source

source :: forall f o. Functor f => f o -> Source f o

Wrap an effectful value into a source. The effect will be repeated indefinitely.

For example, generating ten instances of the value 1:

take 10 $ source (pure 1)

#sink

sink :: forall f i. Functor f => (i -> f Unit) -> Sink f i

Construct a machine which executes an effectful computation on its inputs.

For example, logging could be used as a sink:

take 10 $ source (pure 1) >>> sink logShow

#stepMealy

stepMealy :: forall f i o. i -> MealyT f i o -> f (Step f i o)

Execute (unroll) a single step on a machine.

#runMealy

runMealy :: forall f. Monad f => MealyT f Unit Unit -> f Unit

Run a machine as an effectful computatation.

For example:

runMealy $ take 10 $ source (pure 1) >>> sink logShow

#pureMealy

pureMealy :: forall f i o. Applicative f => (i -> Step f i o) -> MealyT f i o

Wrap a pure function into a machine. The function can either terminate via Halt, or Emit a value and then decide whether to Halt, continue with a different function, or (usually) wrap itself via pureMealy recursively.

For example, we can Halt on zero:

haltOn0 :: forall f. Applicative f => MealyT f Int Int
haltOn0 = pureMealy go
  where
    go 0 = Halt
    go n = Emit n (pureMealy haltOn0)

#mealy

mealy :: forall f i o. (i -> f (Step f i o)) -> MealyT f i o

Wrap an effectful function into a machine. See pureMealy for an example using pure functions.

#halt

halt :: forall f i o. Applicative f => MealyT f i o

A machine which halts for any input.

#take

take :: forall f i o. Applicative f => Int -> MealyT f i o -> MealyT f i o

Limit the number of outputs of a machine. After using up the n allotted outputs, the machine will halt.

#drop

drop :: forall f i o. Monad f => Int -> MealyT f i o -> MealyT f i o

Skip a number of outputs for a machine.

#loop

loop :: forall f i o. Monad f => MealyT f i o -> MealyT f i o

Loop a machine forever.

#toUnfoldable

toUnfoldable :: forall f g i o. Unfoldable g => Comonad f => i -> MealyT f i o -> g o

Extract all the outputs of a machine, given some input.

#zipWith

zipWith :: forall f i a b c. Apply f => (a -> b -> c) -> MealyT f i a -> MealyT f i b -> MealyT f i c

Zip two machines together under some function f.

#scanl

scanl :: forall f i a b. Functor f => (b -> a -> b) -> b -> MealyT f i a -> MealyT f i b

Accumulate the outputs of a machine into a new machine.

#collect

collect :: forall f i o. Functor f => MealyT f i o -> MealyT f i (List o)

Accumulates the outputs of a machine as a List.

#singleton

singleton :: forall f i o. Applicative f => o -> MealyT f i o

Creates a machine which emits a single value before halting.

#fromMaybe

fromMaybe :: forall f i o. Applicative f => Maybe o -> MealyT f i o

Creates a machine which either emits a single value before halting (for Just), or just halts (in the case of Nothing).

#fromArray

fromArray :: forall f i o. Monad f => Array o -> MealyT f i o

Creates a machine which emits all the values of the array before halting.

#msplit

msplit :: forall f i o. Applicative f => MealyT f i o -> MealyT f i (Maybe (Tuple o (MealyT f i o)))

Unwrap a machine such that its output is either Nothing in case it would halt, or Just the output value and the next computation.

#interleave

interleave :: forall f i o. Monad f => MealyT f i o -> MealyT f i o -> MealyT f i o

Interleaves the values of two machines with matching inputs and outputs.

#once

once :: forall f s a. Applicative f => MealyT f s a -> MealyT f s a

Takes a single output from a machine.

#when

when :: forall f i a b. Monad f => MealyT f i a -> (a -> MealyT f i b) -> MealyT f i b

Given a machine and a continuation, it will pass outputs from the machine to the continuation as long as possible until one of them halts.

#ifte

ifte :: forall f i a b. Monad f => MealyT f i a -> (a -> MealyT f i b) -> MealyT f i b -> MealyT f i b

If then else: given a machine producing a, a continuation f, and a machine producing b, generate a machine which will grab outputs from the first machine and pass them over to the continuation as long as neither halts. Once the process halts, the second (b) machine is returned.

#wrapEffect

wrapEffect :: forall f i o. Applicative f => f o -> MealyT f i o

Creates a machine which wraps an effectful computation and ignores its input.

Modules