| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Data.Automaton
Synopsis
- newtype Automaton (m :: Type -> Type) a b = Automaton {
- getAutomaton :: OptimizedStreamT (ReaderT a m) b
- unfold :: forall (m :: Type -> Type) s a b. Applicative m => s -> (a -> s -> Result s b) -> Automaton m a b
- unfoldM :: s -> (a -> s -> m (Result s b)) -> Automaton m a b
- unfold_ :: forall (m :: Type -> Type) s a. Applicative m => s -> (a -> s -> s) -> Automaton m a s
- arrM :: Functor m => (a -> m b) -> Automaton m a b
- constM :: Functor m => m b -> Automaton m a b
- hoistS :: Monad m => (forall x. m x -> n x) -> Automaton m a b -> Automaton n a b
- liftS :: forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a b. (MonadTrans t, Monad m, Functor (t m)) => Automaton m a b -> Automaton (t m) a b
- feedback :: forall (m :: Type -> Type) c a b. Functor m => c -> Automaton m (a, c) (b, c) -> Automaton m a b
- stepAutomaton :: Functor m => Automaton m a b -> a -> m (Result (Automaton m a b) b)
- reactimate :: Monad m => Automaton m () () -> m void
- embed :: Monad m => Automaton m a b -> [a] -> m [b]
- withAutomaton :: (Functor m1, Functor m2) => (forall s. (a1 -> m1 (Result s b1)) -> a2 -> m2 (Result s b2)) -> Automaton m1 a1 b1 -> Automaton m2 a2 b2
- withAutomaton_ :: (Functor m1, Functor m2) => (forall s. m1 (Result s b1) -> m2 (Result s b2)) -> Automaton m1 a b1 -> Automaton m2 a b2
- mapMaybeS :: forall (m :: Type -> Type) a b. Monad m => Automaton m a b -> Automaton m (Maybe a) (Maybe b)
- traverseS :: forall (m :: Type -> Type) f a b. (Monad m, Traversable f) => Automaton m a b -> Automaton m (f a) (f b)
- traverseS_ :: forall (m :: Type -> Type) f a b. (Monad m, Traversable f) => Automaton m a b -> Automaton m (f a) ()
- parallelyList :: forall (m :: Type -> Type) a b. Applicative m => Automaton m a b -> Automaton m [a] [b]
- parallely :: forall (m :: Type -> Type) t a b. (Applicative m, Witherable t, Align t) => Automaton m a b -> Automaton m (t a) (t b)
- fromStream :: forall (m :: Type -> Type) a any. Monad m => StreamT m a -> Automaton m any a
- toStreamT :: forall (m :: Type -> Type) a b. Functor m => Automaton m a b -> StreamT (ReaderT a m) b
- handleAutomaton_ :: forall (m :: Type -> Type) a b i. Monad m => (forall (m1 :: Type -> Type). Monad m1 => StreamT m1 a -> StreamT m1 b) -> Automaton m i a -> Automaton m i b
- handleAutomatonF_ :: forall (m :: Type -> Type) a b i. Functor m => (forall (m1 :: Type -> Type). Functor m1 => StreamT m1 a -> StreamT m1 b) -> Automaton m i a -> Automaton m i b
- handleAutomaton :: forall (m :: Type -> Type) a b c (n :: Type -> Type) d. Functor m => (StreamT (ReaderT a m) b -> StreamT (ReaderT c n) d) -> Automaton m a b -> Automaton n c d
- concatS :: forall (m :: Type -> Type) a b. Monad m => Automaton m a [b] -> Automaton m a b
- handleEffect :: (Monad m, Monad eff, Functor sig) => (forall x. sig x -> eff x) -> (forall x. eff x -> m (sig x)) -> Automaton eff a b -> Automaton m a (sig b)
- withSideEffect :: Monad m => (a -> m b) -> Automaton m a a
- accumulateWith :: forall (m :: Type -> Type) a b. Monad m => (a -> b -> b) -> b -> Automaton m a b
- mappendFrom :: forall w (m :: Type -> Type). (Monoid w, Monad m) => w -> Automaton m w w
- mappendFromR :: forall w (m :: Type -> Type). (Monoid w, Monad m) => w -> Automaton m w w
- delay :: forall (m :: Type -> Type) a. Applicative m => a -> Automaton m a a
- prepend :: forall (m :: Type -> Type) b a. Monad m => b -> Automaton m a b -> Automaton m a b
- mappendS :: forall w (m :: Type -> Type). (Monoid w, Monad m) => Automaton m w w
- sumFrom :: forall v s (m :: Type -> Type). (VectorSpace v s, Monad m) => v -> Automaton m v v
- sumS :: forall (m :: Type -> Type) v s. (Monad m, VectorSpace v s) => Automaton m v v
- sumN :: forall (m :: Type -> Type) a. (Monad m, Num a) => Automaton m a a
- count :: forall n (m :: Type -> Type) a. (Num n, Monad m) => Automaton m a n
- lastS :: forall (m :: Type -> Type) a. Monad m => a -> Automaton m (Maybe a) a
- initialised :: Monad m => (a -> m b) -> Automaton m a b
- initialised_ :: Monad m => m b -> Automaton m a b
Constructing automata
newtype Automaton (m :: Type -> Type) a b Source #
An effectful automaton in coalgebraic encoding.
m: The monad in which the automaton performs side effects.a: The type of inputs the automaton constantly consumes.b: The type of outputs the automaton constantly produces.
An effectful automaton with input a is the same as an effectful stream
with the additional effect of reading an input value a on every step.
This is why automata are defined here as streams.
The API of automata follows that of streams (StreamT and OptimizedStreamT) closely.
The prominent addition in automata is now that they are instances of the Category, Arrow, Profunctor,
and related type classes.
This allows for more ways of creating or composing them.
For example, you can sequentially and parallely compose two automata: @ automaton1 :: Automaton m a b automaton2 :: Automaton m b c
sequentially :: Automaton m a c sequentially = automaton1 >>> automaton2
inParallel :: Automaton m (a, b) (b, c) inParallel = automaton1 *** automaton2 @ In sequential composition, the output of the first automaton is passed as input to the second one. In parallel composition, both automata receive input simulataneously and process it independently.
Through the Arrow type class, you can use arr to create an automaton from a pure function,
and more generally use the arrow syntax extension to define automata.
Constructors
| Automaton | |
Fields
| |
Instances
| Monad m => Category (Automaton m :: Type -> Type -> Type) Source # | |
| Monad m => Arrow (Automaton m) Source # | |
Defined in Data.Automaton Methods arr :: (b -> c) -> Automaton m b c # first :: Automaton m b c -> Automaton m (b, d) (c, d) # second :: Automaton m b c -> Automaton m (d, b) (d, c) # (***) :: Automaton m b c -> Automaton m b' c' -> Automaton m (b, b') (c, c') # (&&&) :: Automaton m b c -> Automaton m b c' -> Automaton m b (c, c') # | |
| Monad m => ArrowChoice (Automaton m) Source # | |
Defined in Data.Automaton Methods left :: Automaton m b c -> Automaton m (Either b d) (Either c d) # right :: Automaton m b c -> Automaton m (Either d b) (Either d c) # (+++) :: Automaton m b c -> Automaton m b' c' -> Automaton m (Either b b') (Either c c') # (|||) :: Automaton m b d -> Automaton m c d -> Automaton m (Either b c) d # | |
| MonadFix m => ArrowLoop (Automaton m) Source # | Caution, this can make your program hang. Try to use |
Defined in Data.Automaton | |
| (Monad m, Alternative m) => ArrowPlus (Automaton m) Source # | |
| (Monad m, Alternative m) => ArrowZero (Automaton m) Source # | |
Defined in Data.Automaton | |
| Monad m => Choice (Automaton m) Source # | |
| Monad m => Cochoice (Automaton m) Source # | |
| Monad m => Strong (Automaton m) Source # | |
| Monad m => Traversing (Automaton m) Source # | Step an automaton several steps at once, depending on how long the input is. |
Defined in Data.Automaton | |
| Functor m => Profunctor (Automaton m) Source # | |
Defined in Data.Automaton Methods dimap :: (a -> b) -> (c -> d) -> Automaton m b c -> Automaton m a d # lmap :: (a -> b) -> Automaton m b c -> Automaton m a c # rmap :: (b -> c) -> Automaton m a b -> Automaton m a c # (#.) :: forall a b c q. Coercible c b => q b c -> Automaton m a b -> Automaton m a c # (.#) :: forall a b c q. Coercible b a => Automaton m b c -> q a b -> Automaton m a c # | |
| Alternative m => Alternative (Automaton m a) Source # | |
| Applicative m => Applicative (Automaton m a) Source # | |
Defined in Data.Automaton Methods pure :: a0 -> Automaton m a a0 # (<*>) :: Automaton m a (a0 -> b) -> Automaton m a a0 -> Automaton m a b # liftA2 :: (a0 -> b -> c) -> Automaton m a a0 -> Automaton m a b -> Automaton m a c # (*>) :: Automaton m a a0 -> Automaton m a b -> Automaton m a b # (<*) :: Automaton m a a0 -> Automaton m a b -> Automaton m a a0 # | |
| Functor m => Functor (Automaton m a) Source # | |
| Selective m => Selective (Automaton m a) Source # | |
| Align m => Align (Automaton m a) Source # | |
Defined in Data.Automaton | |
| Semialign m => Semialign (Automaton m a) Source # | Run both automata in parallel and use |
| (Applicative m, Floating b) => Floating (Automaton m a b) Source # | |
Defined in Data.Automaton Methods exp :: Automaton m a b -> Automaton m a b # log :: Automaton m a b -> Automaton m a b # sqrt :: Automaton m a b -> Automaton m a b # (**) :: Automaton m a b -> Automaton m a b -> Automaton m a b # logBase :: Automaton m a b -> Automaton m a b -> Automaton m a b # sin :: Automaton m a b -> Automaton m a b # cos :: Automaton m a b -> Automaton m a b # tan :: Automaton m a b -> Automaton m a b # asin :: Automaton m a b -> Automaton m a b # acos :: Automaton m a b -> Automaton m a b # atan :: Automaton m a b -> Automaton m a b # sinh :: Automaton m a b -> Automaton m a b # cosh :: Automaton m a b -> Automaton m a b # tanh :: Automaton m a b -> Automaton m a b # asinh :: Automaton m a b -> Automaton m a b # acosh :: Automaton m a b -> Automaton m a b # atanh :: Automaton m a b -> Automaton m a b # log1p :: Automaton m a b -> Automaton m a b # expm1 :: Automaton m a b -> Automaton m a b # | |
| (Applicative m, Num b) => Num (Automaton m a b) Source # | |
Defined in Data.Automaton Methods (+) :: Automaton m a b -> Automaton m a b -> Automaton m a b # (-) :: Automaton m a b -> Automaton m a b -> Automaton m a b # (*) :: Automaton m a b -> Automaton m a b -> Automaton m a b # negate :: Automaton m a b -> Automaton m a b # abs :: Automaton m a b -> Automaton m a b # signum :: Automaton m a b -> Automaton m a b # fromInteger :: Integer -> Automaton m a b # | |
| (Applicative m, Fractional b) => Fractional (Automaton m a b) Source # | |
| (Eq s, Floating s, VectorSpace v s, Applicative m) => VectorSpace (Automaton m a v) (Automaton m a s) Source # | |
Defined in Data.Automaton Methods zeroVector :: Automaton m a v # (*^) :: Automaton m a s -> Automaton m a v -> Automaton m a v # (^/) :: Automaton m a v -> Automaton m a s -> Automaton m a v # (^+^) :: Automaton m a v -> Automaton m a v -> Automaton m a v # (^-^) :: Automaton m a v -> Automaton m a v -> Automaton m a v # negateVector :: Automaton m a v -> Automaton m a v # dot :: Automaton m a v -> Automaton m a v -> Automaton m a s # | |
Arguments
| :: forall (m :: Type -> Type) s a b. Applicative m | |
| => s | The initial state |
| -> (a -> s -> Result s b) | The step function |
| -> Automaton m a b |
Create an Automaton from a state and a pure step function.
Create an Automaton from a state and an effectful step function.
Arguments
| :: forall (m :: Type -> Type) s a. Applicative m | |
| => s | The initial state |
| -> (a -> s -> s) | The step function |
| -> Automaton m a s |
Like unfold, but output the current state.
arrM :: Functor m => (a -> m b) -> Automaton m a b Source #
Consume an input and produce output effectfully, without keeping internal state
constM :: Functor m => m b -> Automaton m a b Source #
Produce output effectfully, without keeping internal state
hoistS :: Monad m => (forall x. m x -> n x) -> Automaton m a b -> Automaton n a b Source #
Apply an arbitrary monad morphism to an automaton.
liftS :: forall (t :: (Type -> Type) -> Type -> Type) (m :: Type -> Type) a b. (MonadTrans t, Monad m, Functor (t m)) => Automaton m a b -> Automaton (t m) a b Source #
Lift the monad of an automaton to a transformer.
Arguments
| :: forall (m :: Type -> Type) c a b. Functor m | |
| => c | The additional internal state |
| -> Automaton m (a, c) (b, c) | The original automaton |
| -> Automaton m a b |
Extend the internal state and feed back part of the output to the next input.
This is one of the fundamental ways to incorporate recursive dataflow in automata. Given an automaton which consumes an additional input and produces an additional output, the state of the automaton is extended by a further value. This value is used as the additional input, and the resulting additional output is stored in the internal state for the next step.
Running automata
stepAutomaton :: Functor m => Automaton m a b -> a -> m (Result (Automaton m a b) b) Source #
Run one step of an automaton.
This consumes an input value, performs a side effect, and returns an updated automaton together with an output value.
reactimate :: Monad m => Automaton m () () -> m void Source #
Run an automaton with trivial input and output indefinitely.
If the input and output of an automaton does not contain information,
all of its meaning is in its effects.
This function runs the automaton indefinitely.
Since it will never return with a value, this function also has no output (its output is void).
The only way it can return is if m includes some effect of termination,
e.g. Maybe or Either could terminate with a Nothing or Left value,
or IO can raise an exception.
Run an automaton with given input, for a given number of steps.
Especially for tests and batch processing, it is useful to step an automaton with given input.
Modifying automata
withAutomaton :: (Functor m1, Functor m2) => (forall s. (a1 -> m1 (Result s b1)) -> a2 -> m2 (Result s b2)) -> Automaton m1 a1 b1 -> Automaton m2 a2 b2 Source #
Change the input and output type and effect of an automaton without changing its state type.
withAutomaton_ :: (Functor m1, Functor m2) => (forall s. m1 (Result s b1) -> m2 (Result s b2)) -> Automaton m1 a b1 -> Automaton m2 a b2 Source #
Change the output type and effect of an automaton without changing its state type.
Traversing automata
mapMaybeS :: forall (m :: Type -> Type) a b. Monad m => Automaton m a b -> Automaton m (Maybe a) (Maybe b) Source #
Only step the automaton if the input is Just.
traverseS :: forall (m :: Type -> Type) f a b. (Monad m, Traversable f) => Automaton m a b -> Automaton m (f a) (f b) Source #
Use an Automaton with a variable amount of input.
traverseS_ :: forall (m :: Type -> Type) f a b. (Monad m, Traversable f) => Automaton m a b -> Automaton m (f a) () Source #
Like traverseS, discarding the output.
parallelyList :: forall (m :: Type -> Type) a b. Applicative m => Automaton m a b -> Automaton m [a] [b] Source #
Launch arbitrarily many copies of the automaton in parallel.
- The copies of the automaton are launched on demand as the input lists grow.
- The n-th copy will always receive the n-th input.
- If the input list has length n, the n+1-th automaton copy will not be stepped.
Caution: Uses memory of the order of the largest list that was ever input during runtime.
parallely :: forall (m :: Type -> Type) t a b. (Applicative m, Witherable t, Align t) => Automaton m a b -> Automaton m (t a) (t b) Source #
Launch many copies of the automaton in parallel, depending on the input shape.
- This generalises
parallelyListfrom lists to arbitraryWitherables satisfyingAlignsuch asMaps,Seq'uences, and other data structures. - The copies of the automaton are launched on demand as the input shape changes in such a way that there are new positions.
- The automaton copy on a particular position will always receive the input from that position.
- Only those automaton copies on positions with a matching input will be stepped.
For example, if the first input is a map with keys k1 and k2,
two copies will be started, one for each key.
If the next input map has keys k1 and k3,
the first automaton at key k1 will be stepped,
the copy at k2 will not be stepped and keeps its state,
and a new copy will be launched at k3.
Caution: Uses memory of the order of the largest input that was ever input during runtime.
Interaction with StreamT
fromStream :: forall (m :: Type -> Type) a any. Monad m => StreamT m a -> Automaton m any a Source #
Create an Automaton from a stream.
It will ignore its input.
toStreamT :: forall (m :: Type -> Type) a b. Functor m => Automaton m a b -> StreamT (ReaderT a m) b Source #
handleAutomaton_ :: forall (m :: Type -> Type) a b i. Monad m => (forall (m1 :: Type -> Type). Monad m1 => StreamT m1 a -> StreamT m1 b) -> Automaton m i a -> Automaton m i b Source #
Given a transformation of streams, apply it to an automaton, without changing the input.
handleAutomatonF_ :: forall (m :: Type -> Type) a b i. Functor m => (forall (m1 :: Type -> Type). Functor m1 => StreamT m1 a -> StreamT m1 b) -> Automaton m i a -> Automaton m i b Source #
Like handleAutomaton_, but with fewer constraints.
handleAutomaton :: forall (m :: Type -> Type) a b c (n :: Type -> Type) d. Functor m => (StreamT (ReaderT a m) b -> StreamT (ReaderT c n) d) -> Automaton m a b -> Automaton n c d Source #
Given a transformation of streams, apply it to an automaton. The input can be accessed through the ReaderT effect.
Buffering
Handling effects
Arguments
| :: (Monad m, Monad eff, Functor sig) | |
| => (forall x. sig x -> eff x) | Send a declarative effect in the signature to the effect carrier monad. |
| -> (forall x. eff x -> m (sig x)) | Interpret the effect in |
| -> Automaton eff a b | |
| -> Automaton m a (sig b) |
Continuously interpret a first order effect.
Several types are relevant here:
sig: An effect signature functor, that encodes one effect. For example,for raising exceptions of typeEitheree, or(w, )for a logging effect.eff: A monad that carries the effect. This can be a monad transformer stack including a transformer corresponding tosig, such asExceptTforEither. It can also be theEffmonad of an effect library such aspolysemy,bluefin,effectfuland so on.m: The underlying monad in which the interpretation is performed, think "effwithout the effects fromsig".
This function takes two functions, one to create effects in eff from the signature, and the other to fully interpret them in m,
storing the complete effect information in sig again.
It then executes the given automaton, extracting the effect by interpretation, and sending it back in.
The execution semantics is that of the monad eff, while the pure effect of the whole computation is returned in the output, encoded in sig.
For examples, see handleEffect.
Examples
Arguments
| :: Monad m | |
| => (a -> m b) | For every value passing through the automaton, this function is called and the resulting side effect performed. |
| -> Automaton m a a |
Pass through a value unchanged, and perform a side effect depending on it
Arguments
| :: forall (m :: Type -> Type) a b. Monad m | |
| => (a -> b -> b) | The accumulation function |
| -> b | The initial accumulator |
| -> Automaton m a b |
Accumulate the input, output the accumulator.
mappendFrom :: forall w (m :: Type -> Type). (Monoid w, Monad m) => w -> Automaton m w w Source #
Like accumulateWith, with mappend as the accumulation function.
The new values are mappended from the left.
mappendFromR :: forall w (m :: Type -> Type). (Monoid w, Monad m) => w -> Automaton m w w Source #
Like mappendFrom, but mappending new values from the right.
Arguments
| :: forall (m :: Type -> Type) a. Applicative m | |
| => a | The value to output on the first step |
| -> Automaton m a a |
Delay the input by one step.
prepend :: forall (m :: Type -> Type) b a. Monad m => b -> Automaton m a b -> Automaton m a b Source #
Delay an automaton by one step by prepending one value to the output.
On the first step, the given initial output is returned. On all subsequent steps, the automaton is stepped with the previous input.
mappendS :: forall w (m :: Type -> Type). (Monoid w, Monad m) => Automaton m w w Source #
Like mappendFrom, initialised at mempty.
sumFrom :: forall v s (m :: Type -> Type). (VectorSpace v s, Monad m) => v -> Automaton m v v Source #
Sum up all inputs so far, with an explicit initial value.
sumS :: forall (m :: Type -> Type) v s. (Monad m, VectorSpace v s) => Automaton m v v Source #
Like sumFrom, initialised at 0.
sumN :: forall (m :: Type -> Type) a. (Monad m, Num a) => Automaton m a a Source #
Sum up all inputs so far, initialised at 0.
count :: forall n (m :: Type -> Type) a. (Num n, Monad m) => Automaton m a n Source #
Count the natural numbers, beginning at 1.
lastS :: forall (m :: Type -> Type) a. Monad m => a -> Automaton m (Maybe a) a Source #
Remembers the last Just value, defaulting to the given initialisation value.
initialised :: Monad m => (a -> m b) -> Automaton m a b Source #
Call the monadic action once on the first tick and provide its result indefinitely.
initialised_ :: Monad m => m b -> Automaton m a b Source #
Like initialised, but ignores the input.