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

Rename compose to sequential #50

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
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
8 changes: 4 additions & 4 deletions docs/how-to-create-a-machine.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ as arrows between inputs, on the left, and outputs, on the right.
The `StateMachine a b` data type has six constructors which we can use to construct a machine:

- `Basic`
- `Compose`
- `Sequential`
- `Parallel`
- `Alternative`
- `Feedback`
- `Kleisli`

Let's start with the last five.

## `Compose`
## `Sequential`

```haskell
Compose
Sequential
:: StateMachine a b
-> StateMachine b c
-> StateMachine a c
Expand Down Expand Up @@ -185,7 +185,7 @@ Kleisli
-> StateMachineT m a [c]
```

is very similar to `Compose`, but it allows us to compose machines which emit multiple outputs.
is very similar to `Sequential`, but it allows us to compose machines which emit multiple outputs.

Consider two machines

Expand Down
4 changes: 2 additions & 2 deletions spec/Crem/Render/RenderFlowSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ spec =
, MachineLabel "lockMachine"
)

it "renders correctly a Compose machine" $ do
it "renders correctly a Sequential machine" $ do
renderFlow
@Identity
(BinaryLabel (LeafLabel "show") (LeafLabel "length"))
( Compose
( Sequential
(stateless $ show @Int)
(stateless length)
)
Expand Down
11 changes: 0 additions & 11 deletions src/Crem/BaseMachine.hs
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,6 @@ instance Applicative m => Choice (BaseMachineT m topology) where
Right a -> Right <$> action state a
}

-- -- | see https://hackage.haskell.org/package/profunctors-5.6.2/docs/Data-Profunctor-Sieve.html#v:cosieve
-- -- This is basically saying that we can interpret a `BaseMachineT m topology a b`
-- -- as a function from a `NonEmpty a` to `b`
-- instance Cosieve (BaseMachineT m topology) NonEmpty where
-- cosieve :: BaseMachineT m topology a b -> NonEmpty a -> m b
-- cosieve machine (a0 :| as0) =
-- case runBaseMachineT machine a0 of
-- (b, machine') -> case as0 of
-- [] -> b
-- a1 : as1 -> cosieve machine' (a1 :| as1)

-- | A value of type `InitialState state` describes the initial state of a
-- state machine, describing the initial `vertex` in the `topology` and the
-- actual initial data of type `state vertex`
Expand Down
2 changes: 1 addition & 1 deletion src/Crem/Render/Render.hs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ renderUntypedGraph (UntypedGraph graph) = renderGraph graph
machineAsGraph :: StateMachineT m input output -> UntypedGraph
machineAsGraph (Basic baseMachine) =
UntypedGraph (baseMachineAsGraph baseMachine)
machineAsGraph (Compose machine1 machine2) =
machineAsGraph (Sequential machine1 machine2) =
untypedProductGraph
(machineAsGraph machine1)
(machineAsGraph machine2)
Expand Down
9 changes: 1 addition & 8 deletions src/Crem/Render/RenderFlow.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ renderFlow (LeafLabel label) (Basic machine) =
, label
, label
)
renderFlow (BinaryLabel leftLabels rightLabels) (Compose machine1 machine2) = do
renderFlow (BinaryLabel leftLabels rightLabels) (Sequential machine1 machine2) = do
(leftMermaid, leftLabelIn, leftLabelOut) <- renderFlow leftLabels machine1
(rightMermaid, rightLabelIn, rightLabelOut) <- renderFlow rightLabels machine2
Right
Expand Down Expand Up @@ -87,10 +87,3 @@ renderFlow (BinaryLabel leftLabels rightLabels) (Kleisli machine1 machine2) = do
, rightLabelOut
)
renderFlow labels _ = Left $ "Labels structure " <> show labels <> " does not match machine structure" -- TODO: this sucks

-- renderFlow (Basic machine) = renderMermaid $ baseMachineAsGraph machine
-- renderFlow (Compose smt smt') = _wb
-- renderFlow (Parallel smt smt') = _wc
-- renderFlow (Alternative smt smt') = _wd
-- renderFlow (Feedback smt smt') = _we
-- renderFlow (Kleisli smt smt') = _wf
68 changes: 9 additions & 59 deletions src/Crem/StateMachine.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ data StateMachineT m input output where
)
=> BaseMachineT m topology input output
-> StateMachineT m input output
Compose
Sequential
:: StateMachineT m a b
-> StateMachineT m b c
-> StateMachineT m a c
Expand Down Expand Up @@ -59,7 +59,7 @@ type StateMachine a b = forall m. Monad m => StateMachineT m a b
hoist :: (forall x. m x -> n x) -> StateMachineT m a b -> StateMachineT n a b
hoist f machine = case machine of
Basic baseMachine -> Basic $ baseHoist f baseMachine
Compose machine1 machine2 -> Compose (hoist f machine1) (hoist f machine2)
Sequential machine1 machine2 -> Sequential (hoist f machine1) (hoist f machine2)
Parallel machine1 machine2 -> Parallel (hoist f machine1) (hoist f machine2)
Alternative machine1 machine2 -> Alternative (hoist f machine1) (hoist f machine2)
Feedback machine1 machine2 -> Feedback (hoist f machine1) (hoist f machine2)
Expand Down Expand Up @@ -97,20 +97,20 @@ instance Monad m => Category (StateMachineT m) where
id = Basic identity

(.) :: StateMachineT m b c -> StateMachineT m a b -> StateMachineT m a c
(.) = flip Compose
(.) = flip Sequential

-- * Profunctor

instance Applicative m => Profunctor (StateMachineT m) where
lmap :: (a -> b) -> StateMachineT m b c -> StateMachineT m a c
lmap f (Basic baseMachine) = Basic $ lmap f baseMachine
lmap f (Compose machine1 machine2) = Compose (lmap f machine1) machine2
lmap f machine = Compose (stateless f) machine
lmap f (Sequential machine1 machine2) = Sequential (lmap f machine1) machine2
lmap f machine = Sequential (stateless f) machine

rmap :: (b -> c) -> StateMachineT m a b -> StateMachineT m a c
rmap f (Basic baseMachine) = Basic $ rmap f baseMachine
rmap f (Compose machine1 machine2) = Compose machine1 (rmap f machine2)
rmap f machine = Compose machine (stateless f)
rmap f (Sequential machine1 machine2) = Sequential machine1 (rmap f machine2)
rmap f machine = Sequential machine (stateless f)

-- * Strong

Expand All @@ -131,66 +131,16 @@ instance Monad m => Choice (StateMachineT m) where
right' :: StateMachineT m a b -> StateMachineT m (Either c a) (Either c b)
right' = Alternative Control.Category.id

-- -- * Cosieve

-- -- | see https://hackage.haskell.org/package/profunctors-5.6.2/docs/Data-Profunctor-Sieve.html#v:cosieve
-- -- This is basically saying that we can interpret a `StateMachine a b` as a
-- -- function from a `NonEmpty a` to `b`
-- instance Cosieve (StateMachineT m) NonEmpty where
-- cosieve :: StateMachineT m a b -> NonEmpty a -> m b
-- cosieve machine (a0 :| as0) =
-- case run machine a0 of
-- (b, machine') -> case as0 of
-- [] -> b
-- a1 : as1 -> cosieve machine' (a1 :| as1)

-- -- * Corepresentable

-- -- the state space for a machine with a topology containing a single vertex
-- -- and a type of possible states in that vertex
-- data SingleVertexState a (vertex :: ()) where
-- SingleVertexState :: a -> SingleVertexState a '()

-- -- | see https://hackage.haskell.org/package/profunctors-5.6.2/docs/Data-Profunctor-Rep.html#t:Corepresentable
-- -- This is basically saying that we can interpret a function from `NonEmpty a`
-- -- to `b` as a `StateMachine a b`, where we store the tail of the non-empty
-- -- list in the state of the machine.
-- instance Corepresentable (StateMachineT m) where
-- type Corep (StateMachineT m) = NonEmpty

-- cotabulate :: forall a b. (NonEmpty a -> m b) -> StateMachineT m a b
-- cotabulate f =
-- Basic @_ @() @TrivialTopology $
-- BaseMachineT
-- { initialState = InitialState $ SingleVertexState ([] :: [a])
-- , action = \(SingleVertexState as) input ->
-- let
-- allInputs = input : as
-- in
-- ActionResult
-- (SingleVertexState allInputs)
-- (f . fromList . reverse $ allInputs)
-- }

-- -- * Costrong

-- instance Costrong (StateMachineT m) where
-- unfirst :: StateMachineT m (a, c) (b, c) -> StateMachineT m a b
-- unfirst = unfirstCorep

-- unsecond :: StateMachineT m (c, a) (c, b) -> StateMachineT m a b
-- unsecond = unsecondCorep

-- * Run a state machine

-- | Given an `input`, run the machine to get an output and a new version of
-- the machine
run :: Monad m => StateMachineT m a b -> a -> m (b, StateMachineT m a b)
run (Basic baseMachine) a = second Basic <$> runBaseMachineT baseMachine a
run (Compose machine1 machine2) a = do
run (Sequential machine1 machine2) a = do
(output1, machine1') <- run machine1 a
(output2, machine2') <- run machine2 output1
pure (output2, Compose machine1' machine2')
pure (output2, Sequential machine1' machine2')
run (Parallel machine1 machine2) a = do
(output1, machine1') <- run machine1 (fst a)
(output2, machine2') <- run machine2 (snd a)
Expand Down