packages feed

machines 0.1.2 → 0.2.1

raw patch · 13 files changed

+187/−149 lines, 13 filesdep +pointedPVP ok

version bump matches the API change (PVP)

Dependencies added: pointed

API changes (from Hackage documentation)

- Data.Machine.Plan: instance Alternative (PlanT k i o m)
- Data.Machine.Plan: instance Applicative (PlanT k i o m)
- Data.Machine.Plan: instance Functor (PlanT k i o m)
- Data.Machine.Plan: instance Monad (PlanT k i o m)
- Data.Machine.Plan: instance MonadError e m => MonadError e (PlanT k i o m)
- Data.Machine.Plan: instance MonadIO m => MonadIO (PlanT k i o m)
- Data.Machine.Plan: instance MonadPlus (PlanT k i o m)
- Data.Machine.Plan: instance MonadReader e m => MonadReader e (PlanT k i o m)
- Data.Machine.Plan: instance MonadState s m => MonadState s (PlanT k i o m)
- Data.Machine.Plan: instance MonadTrans (PlanT k i o)
- Data.Machine.Process: after :: Monad m => MachineT m k a b -> ProcessT m b c -> MachineT m k a c
- Data.Machine.Type: instance (Monad m, Profunctor k) => Profunctor (MachineT m k)
- Data.Machine.Type: instance (k ~ Is, Monad m) => Category (MachineT m k)
- Data.Machine.Type: instance Functor (Step k i o)
- Data.Machine.Type: instance Monad m => Functor (MachineT m k i)
- Data.Machine.Type: instance m ~ Identity => Foldable (MachineT m k i)
+ Data.Machine.Mealy: instance Pointed (Mealy a)
+ Data.Machine.Moore: instance Copointed (Moore a)
+ Data.Machine.Moore: instance Pointed (Moore a)
+ Data.Machine.Plan: instance Alternative (PlanT k o m)
+ Data.Machine.Plan: instance Applicative (PlanT k o m)
+ Data.Machine.Plan: instance Functor (PlanT k o m)
+ Data.Machine.Plan: instance Monad (PlanT k o m)
+ Data.Machine.Plan: instance MonadError e m => MonadError e (PlanT k o m)
+ Data.Machine.Plan: instance MonadIO m => MonadIO (PlanT k o m)
+ Data.Machine.Plan: instance MonadPlus (PlanT k o m)
+ Data.Machine.Plan: instance MonadReader e m => MonadReader e (PlanT k o m)
+ Data.Machine.Plan: instance MonadState s m => MonadState s (PlanT k o m)
+ Data.Machine.Plan: instance MonadTrans (PlanT k o)
+ Data.Machine.Plan: instance MonadWriter w m => MonadWriter w (PlanT k o m)
+ Data.Machine.Process: (<~) :: Monad m => ProcessT m b c -> MachineT m k b -> MachineT m k c
+ Data.Machine.Process: (~>) :: Monad m => MachineT m k b -> ProcessT m b c -> MachineT m k c
+ Data.Machine.Process: echo :: Process a a
+ Data.Machine.Type: applied :: (Appliance k, Monad m) => MachineT m k (a -> b) -> MachineT m k a -> MachineT m k b
+ Data.Machine.Type: class Appliance k
+ Data.Machine.Type: instance (Monad m, Appliance k) => Applicative (MachineT m k)
+ Data.Machine.Type: instance Functor (Step k o)
+ Data.Machine.Type: instance Monad m => Functor (MachineT m k)
+ Data.Machine.Type: instance Monad m => Pointed (MachineT m k)
+ Data.Machine.Type: instance m ~ Identity => Foldable (MachineT m k)
- Data.Machine.Plan: PlanT :: (forall r. (a -> m r) -> (o -> m r -> m r) -> (forall z. (z -> m r) -> k i z -> m r -> m r) -> m r -> m r) -> PlanT k i o m a
+ Data.Machine.Plan: PlanT :: (forall r. (a -> m r) -> (o -> m r -> m r) -> (forall z. (z -> m r) -> k z -> m r -> m r) -> m r -> m r) -> PlanT k o m a
- Data.Machine.Plan: await :: Category k => Plan k i o i
+ Data.Machine.Plan: await :: Category k => Plan (k i) o i
- Data.Machine.Plan: awaits :: k i j -> Plan k i o j
+ Data.Machine.Plan: awaits :: k i -> Plan k o i
- Data.Machine.Plan: newtype PlanT k i o m a
+ Data.Machine.Plan: newtype PlanT k o m a
- Data.Machine.Plan: runPlan :: PlanT k i o Identity a -> (a -> r) -> (o -> r -> r) -> (forall z. (z -> r) -> k i z -> r -> r) -> r -> r
+ Data.Machine.Plan: runPlan :: PlanT k o Identity a -> (a -> r) -> (o -> r -> r) -> (forall z. (z -> r) -> k z -> r -> r) -> r -> r
- Data.Machine.Plan: runPlanT :: PlanT k i o m a -> forall r. (a -> m r) -> (o -> m r -> m r) -> (forall z. (z -> m r) -> k i z -> m r -> m r) -> m r -> m r
+ Data.Machine.Plan: runPlanT :: PlanT k o m a -> forall r. (a -> m r) -> (o -> m r -> m r) -> (forall z. (z -> m r) -> k z -> m r -> m r) -> m r -> m r
- Data.Machine.Plan: stop :: Plan k i o a
+ Data.Machine.Plan: stop :: Plan k o a
- Data.Machine.Plan: type Plan k i o a = forall m. PlanT k i o m a
+ Data.Machine.Plan: type Plan k o a = forall m. PlanT k o m a
- Data.Machine.Plan: yield :: o -> Plan k i o ()
+ Data.Machine.Plan: yield :: o -> Plan k o ()
- Data.Machine.Process: process :: Monad m => (forall a. k i a -> i' -> a) -> MachineT m k i o -> ProcessT m i' o
+ Data.Machine.Process: process :: Monad m => (forall a. k a -> i -> a) -> MachineT m k o -> ProcessT m i o
- Data.Machine.Process: type Process a b = Machine Is a b
+ Data.Machine.Process: type Process a b = Machine (Is a) b
- Data.Machine.Process: type ProcessT m a b = MachineT m Is a b
+ Data.Machine.Process: type ProcessT m a b = MachineT m (Is a) b
- Data.Machine.Source: type Source b = forall k a. Machine k a b
+ Data.Machine.Source: type Source b = forall k. Machine k b
- Data.Machine.Source: type SourceT m b = forall k a. MachineT m k a b
+ Data.Machine.Source: type SourceT m b = forall k. MachineT m k b
- Data.Machine.Tee: L :: T (a, b) a
+ Data.Machine.Tee: L :: T a b a
- Data.Machine.Tee: R :: T (a, b) b
+ Data.Machine.Tee: R :: T a b b
- Data.Machine.Tee: data T i c
+ Data.Machine.Tee: data T a b c
- Data.Machine.Tee: type Tee a b c = Machine T (a, b) c
+ Data.Machine.Tee: type Tee a b c = Machine (T a b) c
- Data.Machine.Tee: type TeeT m a b c = MachineT m T (a, b) c
+ Data.Machine.Tee: type TeeT m a b c = MachineT m (T a b) c
- Data.Machine.Type: Await :: (t -> r) -> (k i t) -> r -> Step k i o r
+ Data.Machine.Type: Await :: (t -> r) -> (k t) -> r -> Step k o r
- Data.Machine.Type: MachineT :: m (Step k i o (MachineT m k i o)) -> MachineT m k i o
+ Data.Machine.Type: MachineT :: m (Step k o (MachineT m k o)) -> MachineT m k o
- Data.Machine.Type: Stop :: Step k i o r
+ Data.Machine.Type: Stop :: Step k o r
- Data.Machine.Type: Yield :: o -> r -> Step k i o r
+ Data.Machine.Type: Yield :: o -> r -> Step k o r
- Data.Machine.Type: before :: Monad m => MachineT m k i o -> PlanT k i o m a -> MachineT m k i o
+ Data.Machine.Type: before :: Monad m => MachineT m k o -> PlanT k o m a -> MachineT m k o
- Data.Machine.Type: construct :: Monad m => PlanT k i o m a -> MachineT m k i o
+ Data.Machine.Type: construct :: Monad m => PlanT k o m a -> MachineT m k o
- Data.Machine.Type: data Step k i o r
+ Data.Machine.Type: data Step k o r
- Data.Machine.Type: encased :: Monad m => Step k i o (MachineT m k i o) -> MachineT m k i o
+ Data.Machine.Type: encased :: Monad m => Step k o (MachineT m k o) -> MachineT m k o
- Data.Machine.Type: fit :: Monad m => (forall a. k i a -> k' i' a) -> MachineT m k i o -> MachineT m k' i' o
+ Data.Machine.Type: fit :: Monad m => (forall a. k a -> k' a) -> MachineT m k o -> MachineT m k' o
- Data.Machine.Type: newtype MachineT m k i o
+ Data.Machine.Type: newtype MachineT m k o
- Data.Machine.Type: pass :: k i o -> Machine k i o
+ Data.Machine.Type: pass :: k o -> Machine k o
- Data.Machine.Type: repeatedly :: Monad m => PlanT k i o m a -> MachineT m k i o
+ Data.Machine.Type: repeatedly :: Monad m => PlanT k o m a -> MachineT m k o
- Data.Machine.Type: run :: MachineT Identity k a b -> [b]
+ Data.Machine.Type: run :: MachineT Identity k b -> [b]
- Data.Machine.Type: runMachine :: MachineT Identity k i o -> Step k i o (MachineT Identity k i o)
+ Data.Machine.Type: runMachine :: MachineT Identity k o -> Step k o (MachineT Identity k o)
- Data.Machine.Type: runMachineT :: MachineT m k i o -> m (Step k i o (MachineT m k i o))
+ Data.Machine.Type: runMachineT :: MachineT m k o -> m (Step k o (MachineT m k o))
- Data.Machine.Type: runT :: Monad m => MachineT m k a b -> m [b]
+ Data.Machine.Type: runT :: Monad m => MachineT m k b -> m [b]
- Data.Machine.Type: runT_ :: Monad m => MachineT m k a b -> m ()
+ Data.Machine.Type: runT_ :: Monad m => MachineT m k b -> m ()
- Data.Machine.Type: stopped :: Machine k a b
+ Data.Machine.Type: stopped :: Machine k b
- Data.Machine.Type: type Machine k i o = forall m. Monad m => MachineT m k i o
+ Data.Machine.Type: type Machine k o = forall m. Monad m => MachineT m k o
- Data.Machine.Unread: peek :: Plan Unread a b a
+ Data.Machine.Unread: peek :: Plan (Unread a) b a
- Data.Machine.Unread: unread :: a -> Plan Unread a b ()
+ Data.Machine.Unread: unread :: a -> Plan (Unread a) b ()
- Data.Machine.Wye: X :: Y (a, b) a
+ Data.Machine.Wye: X :: Y a b a
- Data.Machine.Wye: Y :: Y (a, b) b
+ Data.Machine.Wye: Y :: Y a b b
- Data.Machine.Wye: Z :: Y (a, b) (Either a b)
+ Data.Machine.Wye: Z :: Y a b (Either a b)
- Data.Machine.Wye: data Y i c
+ Data.Machine.Wye: data Y a b c
- Data.Machine.Wye: type Wye a b c = Machine Y (a, b) c
+ Data.Machine.Wye: type Wye a b c = Machine (Y a b) c
- Data.Machine.Wye: type WyeT m a b c = MachineT m Y (a, b) c
+ Data.Machine.Wye: type WyeT m a b c = MachineT m (Y a b) c

Files

.gitignore view
@@ -2,3 +2,4 @@ TAGS tags docs+wiki
CHANGELOG.markdown view
@@ -1,3 +1,11 @@+0.2.1+-----+* Fixed the `Mealy` Monad++0.2+---+* Removed the input type parameter from (almost) all of the types.+ 0.1 --- * Initial release
README.markdown view
@@ -3,6 +3,8 @@  [![Build Status](https://secure.travis-ci.org/ekmett/machines.png?branch=master)](http://travis-ci.org/ekmett/machines) +*Ceci n'est pas une pipe*+ Machines are demand driven input sources like pipes or conduits, but can support multiple inputs.  You design a `Machine` by writing a `Plan`. You then `construct` the machine.@@ -19,6 +21,7 @@ There is a lot of flexibility when building a machine in choosing between empowering the machine to run its own monadic effects or delegating that responsibility to a custom driver. +A port of this design to scala is available from runarorama/machines  Contact Information -------------------
machines.cabal view
@@ -1,6 +1,6 @@ name:          machines category:      Control, Enumerator-version:       0.1.2+version:       0.2.1 license:       BSD3 cabal-version: >= 1.10 license-file:  LICENSE@@ -33,6 +33,7 @@     comonad      == 3.0.*,     containers   >= 0.3   && < 0.6,     free         >= 3.1.1 && < 3.3,+    pointed      == 3.0.*,     profunctors  == 3.0.*,     semigroups   >= 0.8.3 && < 0.9,     transformers == 0.3.*,
src/Data/Machine/Mealy.hs view
@@ -23,6 +23,7 @@ import Data.Machine.Type import Data.Machine.Process import Data.Profunctor+import Data.Pointed import Data.Semigroup import Data.Sequence as Seq import Prelude hiding ((.),id)@@ -42,6 +43,9 @@   m <* _ = m   _ *> n = n +instance Pointed (Mealy a) where+  point b = r where r = Mealy (const (b, r))+ -- | A 'Mealy' machine modeled with explicit state. unfoldMealy :: (s -> a -> (b, s)) -> s -> Mealy a b unfoldMealy f = go where@@ -52,7 +56,7 @@ instance Monad (Mealy a) where   return b = r where r = Mealy (const (b, r))   m >>= f = Mealy $ \a -> case runMealy m a of-    (b, m') -> (fst (runMealy (f b) a), snd (runMealy (m' >>= f) a))+    (b, m') -> (fst (runMealy (f b) a), m' >>= f)   _ >> n = n  instance Profunctor Mealy where
src/Data/Machine/Moore.hs view
@@ -19,10 +19,12 @@ import Control.Applicative import Control.Comonad import Control.Monad+import Data.Copointed import Data.Machine.Plan import Data.Machine.Type import Data.Machine.Process import Data.Monoid+import Data.Pointed import Data.Profunctor  -- | 'Moore' machines@@ -58,12 +60,18 @@   m <* _ = m   _ *> n = n +instance Pointed (Moore a) where+  point a = r where r = Moore a (const r)+ -- | slow diagonalization instance Monad (Moore a) where   return a = r where r = Moore a (const r)   Moore a k >>= f = case f a of     Moore b _ -> Moore b (k >=> f)   _ >> m = m++instance Copointed (Moore a) where+  copoint (Moore b _) = b  instance Comonad (Moore a) where   extract (Moore b _) = b
src/Data/Machine/Plan.hs view
@@ -33,6 +33,7 @@ import Control.Monad.State.Class import Control.Monad.Reader.Class import Control.Monad.Error.Class+import Control.Monad.Writer.Class import Data.Functor.Identity import Prelude hiding ((.),id) @@ -43,37 +44,37 @@ -- | You can 'construct' a 'Plan' (or 'PlanT'), turning it into a -- 'Data.Machine.Type.Machine' (or 'Data.Machine.Type.MachineT'). ---newtype PlanT k i o m a = PlanT+newtype PlanT k o m a = PlanT   { runPlanT :: forall r.       (a -> m r) ->                                     -- Done a-      (o -> m r -> m r) ->                              -- Yield o (Plan k i o a)-      (forall z. (z -> m r) -> k i z -> m r -> m r) ->  -- forall z. Await (z -> Plan i o a) (k i z) (Plan k i o a)+      (o -> m r -> m r) ->                              -- Yield o (Plan k o a)+      (forall z. (z -> m r) -> k z -> m r -> m r) ->  -- forall z. Await (z -> Plan o a) (k z) (Plan k o a)       m r ->                                            -- Fail       m r   } --- | A @'Plan' k i o a@ is a specification for a pure 'Machine', that reads inputs selected by @k@+-- | A @'Plan' k o a@ is a specification for a pure 'Machine', that reads inputs selected by @k@ -- with types based on @i@, writes values of type @o@, and has intermediate results of type @a@. ----- A @'PlanT' k i o a@ can be used as a @'PlanT' k i o m a@ for any @'Monad' m@.+-- A @'PlanT' k o a@ can be used as a @'PlanT' k o m a@ for any @'Monad' m@. -- -- It is perhaps easier to think of 'Plan' in its un-cps'ed form, which would -- look like: -- -- @--- data 'Plan' k i o a+-- data 'Plan' k o a --   = Done a---   | Yield o (Plan k i o a)---   | forall z. Await (z -> Plan k i o a) (k i z) (Plan k i o a)+--   | Yield o (Plan k o a)+--   | forall z. Await (z -> Plan k o a) (k z) (Plan k o a) --   | Fail -- @-type Plan k i o a = forall m. PlanT k i o m a+type Plan k o a = forall m. PlanT k o m a  -- | Deconstruct a 'Plan' without reference to a 'Monad'.-runPlan :: PlanT k i o Identity a+runPlan :: PlanT k o Identity a         -> (a -> r)         -> (o -> r -> r)-        -> (forall z. (z -> r) -> k i z -> r -> r)+        -> (forall z. (z -> r) -> k z -> r -> r)         -> r         -> r runPlan m kp ke kr kf = runIdentity $ runPlanT m@@ -82,66 +83,74 @@   (\f k (Identity r) -> Identity (kr (runIdentity . f) k r))   (Identity kf) -instance Functor (PlanT k i o m) where+instance Functor (PlanT k o m) where   fmap f (PlanT m) = PlanT $ \k -> m (k . f) -instance Applicative (PlanT k i o m) where+instance Applicative (PlanT k o m) where   pure a = PlanT (\kp _ _ _ -> kp a)   (<*>) = ap -instance Alternative (PlanT k i o m) where+instance Alternative (PlanT k o m) where   empty = PlanT $ \_ _ _ kf -> kf   PlanT m <|> PlanT n = PlanT $ \kp ke kr kf -> m kp ke (\ks kir _ -> kr ks kir (n kp ke kr kf)) (n kp ke kr kf) -instance Monad (PlanT k i o m) where+instance Monad (PlanT k o m) where   return a = PlanT (\kp _ _ _ -> kp a)   PlanT m >>= f = PlanT (\kp ke kr kf -> m (\a -> runPlanT (f a) kp ke kr kf) ke kr kf)   fail _ = PlanT (\_ _ _ kf -> kf) -instance MonadPlus (PlanT k i o m) where+instance MonadPlus (PlanT k o m) where   mzero = empty   mplus = (<|>) -instance MonadTrans (PlanT k i o) where+instance MonadTrans (PlanT k o) where   lift m = PlanT (\kp _ _ _ -> m >>= kp) -instance MonadIO m => MonadIO (PlanT k i o m) where+instance MonadIO m => MonadIO (PlanT k o m) where   liftIO m = PlanT (\kp _ _ _ -> liftIO m >>= kp) -instance MonadState s m => MonadState s (PlanT k i o m) where+instance MonadState s m => MonadState s (PlanT k o m) where   get = lift get   put = lift . put   state f = PlanT $ \kp _ _ _ -> state f >>= kp -instance MonadReader e m => MonadReader e (PlanT k i o m) where+instance MonadReader e m => MonadReader e (PlanT k o m) where   ask = lift ask   reader = lift . reader   local f m = PlanT $ \kp ke kr kf -> local f (runPlanT m kp ke kr kf) -instance MonadError e m => MonadError e (PlanT k i o m) where+instance MonadWriter w m  => MonadWriter w (PlanT k o m) where+  writer = lift . writer+  tell   = lift . tell++  listen m = PlanT $ \kp ke kr kf -> runPlanT m ((kp =<<) . listen . return) ke kr kf++  pass m = PlanT $ \kp ke kr kf -> runPlanT m ((kp =<<) . pass . return) ke kr kf++instance MonadError e m => MonadError e (PlanT k o m) where   throwError = lift . throwError   catchError m k = PlanT $ \kp ke kr kf -> runPlanT m kp ke kr kf `catchError` \e -> runPlanT (k e) kp ke kr kf  -- | Output a result.-yield :: o -> Plan k i o ()+yield :: o -> Plan k o () yield o = PlanT (\kp ke _ _ -> ke o (kp ()))  -- | Wait for input. -- -- @'await' = 'awaits' 'id'@-await :: Category k => Plan k i o i+await :: Category k => Plan (k i) o i await = PlanT (\kp _ kr kf -> kr kp id kf)  -- | Wait for a particular input. -- -- @--- awaits 'L'  :: 'Plan' 'T' (a, b) o a--- awaits 'R'  :: 'Plan' 'T' (a, b) o b--- awaits 'id' :: 'Plan' 'Data.Machine.Is.Is' i o i+-- awaits 'L'  :: 'Plan' ('T' a b) o a+-- awaits 'R'  :: 'Plan' ('T' a b) o b+-- awaits 'id' :: 'Plan' ('Data.Machine.Is.Is' i) o i -- @-awaits :: k i j -> Plan k i o j+awaits :: k i -> Plan k o i awaits h = PlanT $ \kp _ kr -> kr kp h  -- | @'stop' = 'empty'@-stop :: Plan k i o a+stop :: Plan k o a stop = empty
src/Data/Machine/Process.hs view
@@ -20,7 +20,8 @@   , Automaton(..)   , process   -- ** Common Processes-  , after+  , (<~), (~>)+  , echo   , supply   , prepended   , filtered@@ -40,18 +41,21 @@ import Data.Machine.Type import Prelude hiding ((.),id) +infixr 9 <~+infixl 9 ~>+ ------------------------------------------------------------------------------- -- Processes -------------------------------------------------------------------------------  -- | A @'Process' a b@ is a stream transducer that can consume values of type @a@ -- from its input, and produce values of type @b@ for its output.-type Process a b = Machine Is a b+type Process a b = Machine (Is a) b  -- | A @'ProcessT' m a b@ is a stream transducer that can consume values of type @a@ -- from its input, and produce values of type @b@ and has side-effects in the -- 'Monad' @m@.-type ProcessT m a b = MachineT m Is a b+type ProcessT m a b = MachineT m (Is a) b  -- | An 'Automaton' is can be automatically lifted into a 'Process' class Automaton k where@@ -63,13 +67,17 @@     yield (f i)  instance Automaton Is where-  auto Refl = repeatedly $ do-    i <- await-    yield i+  auto Refl = echo +-- | The trivial 'Process' that simply repeats each input it receives.+echo :: Process a a+echo = repeatedly $ do+  i <- await+  yield i+ -- | A 'Process' that prepends the elements of a 'Foldable' onto its input, then repeats its input from there. prepended :: Foldable f => f a -> Process a a-prepended = before id . traverse_ yield+prepended = before echo . traverse_ yield  -- | A 'Process' that only passes through inputs that match a predicate. filtered :: (a -> Bool) -> Process a a@@ -79,7 +87,7 @@  -- | A 'Process' that drops the first @n@, then repeats the rest. dropping :: Int -> Process a a-dropping n = before id $ replicateM_ n await+dropping n = before echo $ replicateM_ n await  -- | A 'Process' that passes through the first @n@ elements from its input then stops taking :: Int -> Process a a@@ -91,7 +99,7 @@  -- | A 'Process' that drops elements while a predicate holds droppingWhile :: (a -> Bool) -> Process a a-droppingWhile p = before id loop where+droppingWhile p = before echo loop where   loop = await >>= \v -> if p v then loop else yield v  -- | Chunk up the input into `n` element lists.@@ -105,23 +113,27 @@     i <- await <|> yield (reverse acc) *> stop     go (i:acc) $! n-1 + -- | Build a new 'Machine' by adding a 'Process' to the output of an old 'Machine' -- -- @--- after :: 'Process' a b   -> 'Process' b c -> 'Process' a c--- after :: 'Data.Machine.Tee.Tee' a b c     -> 'Process' c d -> 'Data.Machine.Tee.Tee' a b d--- after :: 'Machine' k a b -> 'Process' b c -> 'Machine' k a c+-- ('<~') :: 'Process' b c -> 'Process' a b -> 'Process' a c+-- ('<~') :: 'Process' c d -> 'Data.Machine.Tee.Tee' a b c -> 'Data.Machine.Tee.Tee' a b d+-- ('<~') :: 'Process' b c -> 'Machine' k b -> 'Machine' k c -- @-after :: Monad m => MachineT m k a b -> ProcessT m b c -> MachineT m k a c-after ma mp = MachineT $ runMachineT mp >>= \v -> case v of+(<~) :: Monad m => ProcessT m b c -> MachineT m k b -> MachineT m k c+mp <~ ma = MachineT $ runMachineT mp >>= \v -> case v of   Stop          -> return Stop-  Yield o k     -> return $ Yield o (after ma k)+  Yield o k     -> return $ Yield o (k <~ ma)   Await f Refl ff -> runMachineT ma >>= \u -> case u of-    Stop          -> runMachineT $ after stopped ff-    Yield o k     -> runMachineT . after k $ f o-    Await g kg fg -> let mv = MachineT (return v) in-      return $ Await (\a -> after (g a) mv) kg (after fg mv)+    Stop          -> runMachineT $ ff <~ stopped+    Yield o k     -> runMachineT $ f o <~ k+    Await g kg fg -> return $ Await (\a -> MachineT (return v) <~ g a) kg (MachineT (return v) <~ fg) +-- | Flipped ('<~').+(~>) :: Monad m => MachineT m k b -> ProcessT m b c -> MachineT m k c+ma ~> mp = mp <~ ma+ -- | Feed a 'Process' some input. supply :: Monad m => [a] -> ProcessT m a b -> ProcessT m a b supply []         m = m@@ -133,17 +145,13 @@ -- | -- Convert a machine into a process, with a little bit of help. ----- @'process' 'id' = 'id'@--- -- @ -- 'process' 'Data.Machine.Tee.L' :: 'Data.Machine.Process.Process' a c -> 'Data.Machine.Tee.Tee' a b c -- 'process' 'Data.Machine.Tee.R' :: 'Data.Machine.Process.Process' b c -> 'Data.Machine.Tee.Tee' a b c -- 'process' 'id' :: 'Data.Machine.Process.Process' a b -> 'Data.Machine.Process.Process' a b -- @-process :: Monad m => (forall a. k i a -> i' -> a) -> MachineT m k i o -> ProcessT m i' o+process :: Monad m => (forall a. k a -> i -> a) -> MachineT m k o -> ProcessT m i o process f (MachineT m) = MachineT (liftM f' m) where   f' (Yield o k)     = Yield o (process f k)   f' Stop            = Stop   f' (Await g kir h) = Await (process f . g . f kir) Refl (process f h)--
src/Data/Machine/Source.hs view
@@ -33,10 +33,10 @@ -------------------------------------------------------------------------------  -- | A 'Source' never reads from its inputs.-type Source b = forall k a. Machine k a b+type Source b = forall k. Machine k b  -- | A 'SourceT' never reads from its inputs, but may have monadic side-effects.-type SourceT m b = forall k a. MachineT m k a b+type SourceT m b = forall k. MachineT m k b  -- | Repeat the same value, over and over. repeated :: o -> Source o@@ -56,7 +56,7 @@ -- Alternately you can view this as capping the 'Source' end of a 'Process', -- yielding a new 'Source'. ----- @'cap' = 'pipe'@+-- @'cap' l r = l '<~' r@ -- cap :: Process a b -> Source a -> Source b-cap l r = after r l+cap l r = l <~ r
src/Data/Machine/Tee.hs view
@@ -20,7 +20,6 @@   , capL, capR   ) where -import Control.Category import Data.Machine.Is import Data.Machine.Process import Data.Machine.Type@@ -32,15 +31,15 @@ -------------------------------------------------------------------------------  -- | The input descriptor for a 'Tee' or 'TeeT'-data T i c where-  L :: T (a, b) a-  R :: T (a, b) b+data T a b c where+  L :: T a b a+  R :: T a b b  -- | A 'Machine' that can read from two input stream in a deterministic manner.-type Tee a b c = Machine T (a, b) c+type Tee a b c = Machine (T a b) c  -- | A 'Machine' that can read from two input stream in a deterministic manner with monadic side-effects.-type TeeT m a b c = MachineT m T (a, b) c+type TeeT m a b c = MachineT m (T a b) c  -- | Compose a pair of pipes onto the front of a Tee. tee :: Monad m => ProcessT m a a' -> ProcessT m b b' -> TeeT m a' b' c -> TeeT m a b c@@ -60,11 +59,11 @@  -- | Precompose a pipe onto the left input of a tee. addL :: Monad m => ProcessT m a b -> TeeT m b c d -> TeeT m a c d-addL p = tee p id+addL p = tee p echo  -- | Precompose a pipe onto the right input of a tee. addR :: Monad m => ProcessT m b c -> TeeT m a c d -> TeeT m a b d-addR = tee id+addR = tee echo  -- | Tie off one input of a tee by connecting it to a known source. capL :: Monad m => SourceT m a -> TeeT m a b c -> ProcessT m b c@@ -75,6 +74,6 @@ capR s t = fit cappedT $ addR s t  -- | Natural transformation used by 'capL' and 'capR'.-cappedT :: T (a, a) b -> Is a b+cappedT :: T a a b -> Is a b cappedT R = Refl cappedT L = Refl
src/Data/Machine/Type.hs view
@@ -35,6 +35,9 @@   , pass    , stopped++  -- * Applicative Machines+  , Appliance(..)   ) where  import Control.Applicative@@ -42,10 +45,9 @@ import Control.Monad (liftM) import Data.Foldable import Data.Functor.Identity-import Data.Machine.Is import Data.Machine.Plan import Data.Monoid-import Data.Profunctor+import Data.Pointed import Prelude hiding ((.),id)  -------------------------------------------------------------------------------@@ -54,92 +56,105 @@  -- | This is the base functor for a 'Machine' or 'MachineT'. ----- Note: Machines are usually constructed from 'Plan', so this does not need to be CPS'd.-data Step k i o r+-- Note: A 'Machine' is usually constructed from 'Plan', so it does not need to be CPS'd.+data Step k o r   = Stop   | Yield o r-  | forall t. Await (t -> r) (k i t) r+  | forall t. Await (t -> r) (k t) r -instance Functor (Step k i o) where+instance Functor (Step k o) where   fmap _ Stop = Stop   fmap f (Yield o k) = Yield o (f k)   fmap f (Await g kg fg) = Await (f . g) kg (f fg)  -- | A 'MachineT' reads from a number of inputs and may yield results before stopping -- with monadic side-effects.-newtype MachineT m k i o = MachineT { runMachineT :: m (Step k i o (MachineT m k i o)) }+newtype MachineT m k o = MachineT { runMachineT :: m (Step k o (MachineT m k o)) }  -- | A 'Machine' reads from a number of inputs and may yield results before stopping. -- -- A 'Machine' can be used as a @'MachineT' m@ for any @'Monad' m@.-type Machine k i o = forall m. Monad m => MachineT m k i o+type Machine k o = forall m. Monad m => MachineT m k o  -- | @'runMachine' = 'runIdentity' . 'runMachineT'@-runMachine :: MachineT Identity k i o -> Step k i o (MachineT Identity k i o)+runMachine :: MachineT Identity k o -> Step k o (MachineT Identity k o) runMachine = runIdentity . runMachineT --- | Pack a Step of a Machine into a Machine.-encased :: Monad m => Step k i o (MachineT m k i o) -> MachineT m k i o+-- | Pack a 'Step' of a 'Machine' into a 'Machine'.+encased :: Monad m => Step k o (MachineT m k o) -> MachineT m k o encased = MachineT . return -instance Monad m => Functor (MachineT m k i) where+instance Monad m => Functor (MachineT m k) where   fmap f (MachineT m) = MachineT (liftM f' m) where     f' (Yield o xs)    = Yield (f o) (f <$> xs)     f' (Await k kir e) = Await (fmap f . k) kir (f <$> e)     f' Stop            = Stop +instance Monad m => Pointed (MachineT m k) where+  point = repeatedly . yield++-- | An input type that supports merging requests from multiple machines.+class Appliance k where+  applied :: Monad m => MachineT m k (a -> b) -> MachineT m k a -> MachineT m k b++instance (Monad m, Appliance k) => Applicative (MachineT m k) where+  pure = point+  (<*>) = applied+ {--apMachines :: Maybe (Seq i) -> Seq a -> MachineT m k i (a -> b) -> MachineT m k i a -> MachineT m k i b-apMachines is as m n = MachineT $ runMachineT m >>= \u -> case u of-  Stop -> return Stop-  Yield f m' -> case viewl as of-    a :< as' -> return $ Yield (f a) (apMachines is as' m' n)-    EmptyL   -> paMachines is (Seq.singleton f) m' n-  Await k Refl kf -> case is of-    Nothing ->+-- TODO -paMachines :: Maybe (Seq i) -> Seq (a -> b) -> MachineT m k i (a -> b) -> MachineT m k i a -> MachineT m k i b-paMachines is fs m n = MachineT $ runMachineT n >>= \v -> case v of-  Stop -> return Stop-  Yield a n' -> case viewl fs of-    f :< fs' -> return $ Yield (f a) (paMachines is fs' m n')-    EmptyL   -> apMachines is (Seq.singleton a) m n'+instance Appliance (Is i) where+  applied = appliedTo (Just mempty) (Just mempty) id (flip id) where -instance (k ~ Is, Monad m) => Applicative (MachineT m k i) where-  pure = repeatedly . yield-  m <*>  n = runMachineT m >>= \u -> case u of-    Stop       -> return stopped-    Yield f xs ->-    Await f Refl ff ->+-- applied+appliedTo+  :: Maybe (Seq i)+  -> Maybe (i -> MachineT m (Is i) b, MachineT m (Is i) b)+  -> Either (Seq a) (Seq b)+  -> (a -> b -> c)+  -> (b -> a -> c)+  -> MachineT m (Is i) a+  -> MachineT m (Is i) b+  -> MachineT m (Is i) c+appliedTo mis blocking ss f g m n = MachineT $ runMachineT m >>= \v -> case v of+  Stop -> return Stop+  Yield a k -> case ss of+    Left as ->+    Right bs -> case viewl bs of+      b :< bs' -> return $ Yield (f a b) (appliedTo mis bs' f g m n)+      EmptyL   -> runMachine $ appliedTo mis blocking (singleton a) g f n m+  Await ak Refl e -> case mis of+    Nothing -> runMachine $ appliedTo Nothing blocking bs f g e n+    Just is -> case viewl is of+      i :< is' -> runMachine $ appliedTo (Just is') blocking bs f g (ak i) m+      EmptyL -> case blocking of+        Just (bk, be) ->+        Nothing -> runMachine $ appliedTo mis (Just (ak, e))+        | blocking  -> return $ Await (\i -> appliedTo (Just (singleton i)) False f g (ak i) n) Refl $+        | otherwise -> -} -instance (Monad m, Profunctor k) => Profunctor (MachineT m k) where-  rmap = fmap-  lmap f (MachineT m) = MachineT (liftM f' m) where-    f' (Yield o xs)    = Yield o (lmap f xs)-    f' (Await k kir e) = Await (lmap f . k) (lmap f kir) (lmap f e)-    f' Stop            = Stop- -- | Stop feeding input into model, taking only the effects.-runT_ :: Monad m => MachineT m k a b -> m ()-runT_ (MachineT m) = m >>= \v -> case v of+runT_ :: Monad m => MachineT m k b -> m ()+runT_ m = runMachineT m >>= \v -> case v of   Stop        -> return ()   Yield _ k   -> runT_ k   Await _ _ e -> runT_ e  -- | Stop feeding input into model and extract an answer-runT :: Monad m => MachineT m k a b -> m [b]+runT :: Monad m => MachineT m k b -> m [b] runT (MachineT m) = m >>= \v -> case v of   Stop        -> return []   Yield o k   -> liftM (o:) (runT k)   Await _ _ e -> runT e  -- | Run a pure machine and extract an answer.-run :: MachineT Identity k a b -> [b]+run :: MachineT Identity k b -> [b] run = runIdentity . runT  -- | This permits toList to be used on a Machine.-instance (m ~ Identity) => Foldable (MachineT m k i) where+instance (m ~ Identity) => Foldable (MachineT m k) where   foldMap f (MachineT (Identity m)) = go m where     go Stop = mempty     go (Yield o k) = f o `mappend` foldMap f k@@ -149,18 +164,14 @@ -- Connect different kinds of machines. -- -- @'fit' 'id' = 'id'@------ @--- 'fit' 'id' :: 'Data.Machine.Process.Process' a b -> 'Data.Machine.Process.Process' a b--- @-fit :: Monad m => (forall a. k i a -> k' i' a) -> MachineT m k i o -> MachineT m k' i' o+fit :: Monad m => (forall a. k a -> k' a) -> MachineT m k o -> MachineT m k' o fit f (MachineT m) = MachineT (liftM f' m) where   f' (Yield o k)     = Yield o (fit f k)   f' Stop            = Stop   f' (Await g kir h) = Await (fit f . g) (f kir) (fit f h)  -- | Compile a machine to a model.-construct :: Monad m => PlanT k i o m a -> MachineT m k i o+construct :: Monad m => PlanT k o m a -> MachineT m k o construct m = MachineT $ runPlanT m   (const (return Stop))   (\o k -> return (Yield o (MachineT k)))@@ -170,7 +181,7 @@ -- | Generates a model that runs a machine until it stops, then start it up again. -- -- @'repeatedly' m = 'construct' ('Control.Monad.forever' m)@-repeatedly :: Monad m => PlanT k i o m a -> MachineT m k i o+repeatedly :: Monad m => PlanT k o m a -> MachineT m k o repeatedly m = r where   r = MachineT $ runPlanT m     (const (runMachineT r))@@ -179,7 +190,7 @@     (return Stop)  -- | Evaluate a machine until it stops, and then yield answers according to the supplied model.-before :: Monad m => MachineT m k i o -> PlanT k i o m a -> MachineT m k i o+before :: Monad m => MachineT m k o -> PlanT k o m a -> MachineT m k o before (MachineT n) m = MachineT $ runPlanT m   (const n)   (\o k -> return (Yield o (MachineT k)))@@ -196,27 +207,13 @@ -- 'pass' 'Data.Machine.Wye.Y'  :: 'Data.Machine.Wye.Wye' a b b -- 'pass' 'Data.Machine.Wye.Z'  :: 'Data.Machine.Wye.Wye' a b (Either a b) -- @-pass :: k i o -> Machine k i o-pass input = repeatedly $ do-  a <- awaits input+pass :: k o -> Machine k o+pass k = repeatedly $ do+  a <- awaits k   yield a --- | Eventually this will probably revert to @instance 'Monad' m => 'Category' ('MachineT' m 'Is')@-instance (k ~ Is, Monad m) => Category (MachineT m k) where-  id = repeatedly $ do-    i <- await-    yield i--  m . n = MachineT $ runMachineT m >>= \v -> case v of-    Stop          -> return Stop-    Yield a as    -> return $ Yield a (as . n)-    Await f Refl k -> runMachineT n >>= \u -> case u of-      Stop          -> runMachineT $ k . stopped-      Yield b bs    -> runMachineT $ f b . bs-      Await g Refl fg -> return $ Await (\a -> encased v . g a) Refl (encased v . fg)- -- | This is a stopped 'Machine'-stopped :: Machine k a b+stopped :: Machine k b stopped = encased Stop  -------------------------------------------------------------------------------@@ -229,6 +226,6 @@ -- (or 'Data.Machine.Tee.Tee', etc) that produces a single answer. -- -- \"Is that your final answer?\"-sink :: Monad m => (forall o. PlanT k i o m a) -> MachineT m k i a+sink :: Monad m => (forall o. PlanT k o m a) -> MachineT m k a sink m = runPlanT m (\a -> Yield a Stop) id (Await id) Stop -}
src/Data/Machine/Unread.hs view
@@ -25,14 +25,14 @@   Read   :: Unread a a  -- | Peek at the next value in the input stream without consuming it-peek :: Plan Unread a b a+peek :: Plan (Unread a) b a peek = do   a <- awaits Read   awaits (Unread a)   return a  -- | Push back into the input stream-unread :: a -> Plan Unread a b ()+unread :: a -> Plan (Unread a) b () unread a = awaits (Unread a)  -- TODO: make this a class?
src/Data/Machine/Wye.hs view
@@ -33,16 +33,16 @@ -------------------------------------------------------------------------------  -- | The input descriptor for a 'Wye' or 'WyeT'-data Y i c where-  X :: Y (a, b) a            -- block waiting on the left input-  Y :: Y (a, b) b            -- block waiting on the right input-  Z :: Y (a, b) (Either a b) -- block waiting on either input+data Y a b c where+  X :: Y a b a            -- block waiting on the left input+  Y :: Y a b b            -- block waiting on the right input+  Z :: Y a b (Either a b) -- block waiting on either input  -- | A 'Machine' that can read from two input stream in a non-deterministic manner.-type Wye a b c = Machine Y (a, b) c+type Wye a b c = Machine (Y a b) c  -- | A 'Machine' that can read from two input stream in a non-deterministic manner with monadic side-effects.-type WyeT m a b c = MachineT m Y (a, b) c+type WyeT m a b c = MachineT m (Y a b) c  -- | Compose a pair of pipes onto the front of a 'Wye'. @@ -82,11 +82,11 @@  -- | Precompose a pipe onto the left input of a wye. addX :: Monad m => ProcessT m a b -> WyeT m b c d -> WyeT m a c d-addX p = wye p id+addX p = wye p echo  -- | Precompose a pipe onto the right input of a tee. addY :: Monad m => ProcessT m b c -> WyeT m a c d -> WyeT m a b d-addY = wye id+addY = wye echo  -- | Tie off one input of a tee by connecting it to a known source. capX :: Monad m => SourceT m a -> WyeT m a b c -> ProcessT m b c@@ -97,7 +97,7 @@ capY s t = process (capped Left) (addY s t)  -- | Natural transformation used by 'capX' and 'capY'-capped :: (a -> Either a a) -> Y (a, a) b -> a -> b+capped :: (a -> Either a a) -> Y a a b -> a -> b capped _ X = id capped _ Y = id capped f Z = f