-
Notifications
You must be signed in to change notification settings - Fork 46
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
runT is silly; accumulating and simpler version desired #50
Comments
Here's the gist of what I mean. You may be able to find a better approach. -- Run a model until it either produces an
-- output or stops. If the model produces output,
-- both that output and the stepped model are produced.
runTFirstOutput :: Monad m => MachineT m k o -> m (Maybe (o, MachineT m k o))
runTFirstOutput (MachineT m) = do
res <- m
case res of
Stop -> return Nothing
Yield o r -> return $ Just (o, r)
Await _ _ r -> runTFirstOutput r
-- Run a model until it either produces output or stops.
-- If the model produces output, only the output is revealed;
-- the model cannot be resumed.
runTFirst :: Monad m => MachineT m k o -> m (Maybe o)
runTFirst = liftM (fmap fst) . runTFirstOutput
-- Run a model producing elements in some semigroup; accumulate
-- them.
runTS :: (Semigroup o, Monad m) => MachineT m k o -> m (Maybe o)
runTS m = runTFirst (m ~> fold1 (flip (<>)))
-- This could also be written to use endomorphism stuff. Whatever.
runT :: Monad m => MachineT m k o -> m [o]
runT m = runTS (fmap (: []) m) >>= maybe (return []) (return . reverse) |
Actually, there should probably be a separate fold operation in between, specialized to deal with folding a semigroup. It should also be possible to write a more |
OK, this seems a bit better developed: -- Convert a MachineT to a SourceT by blocking off its input.
machineTtoSourceT :: forall m k o . Monad m => MachineT m k o -> SourceT m o
machineTtoSourceT m = construct $ go m
where
go mach = do
res <- lift $ runMachineT mach
case res of
Stop -> stop
Yield o r -> yield o >> go r
Await _ _ r -> go r
-- The exposed polymorphism of SourceT sometimes leads to problems
-- with impredicativity.This version uses Void instead.
type AltSourceT m = MachineT m (Const Void)
machineTtoAltSourceT :: forall m k o . Monad m => MachineT m k o -> AltSourceT m o
machineTtoAltSourceT = machineTtoSourceT
-- Every SourceT is automatically an AltSourceT
sourceTtoAltSourceT :: SourceT m o -> AltSourceT m o
sourceTtoAltSourceT m = m
-- An AltSourceT can't possibly await, so it can be converted to a SourceT
altSourceTtoSourceT :: Monad m => AltSourceT m o -> SourceT m o
altSourceTtoSourceT m = construct $ go m
where
go mach = do
res <- lift $ runMachineT mach
case res of
Stop -> stop
Yield o r -> yield o >> go r
Await _ (Const ab) _ -> absurd ab -- Unreachable
-- Run an AltSourceT until it either produces an
-- output or stops. If the model produces output,
-- both that output and the stepped model are produced.
runAltSourceTFirstOutput :: forall m o . Monad m => AltSourceT m o -> m (Maybe (o, AltSourceT m o))
runAltSourceTFirstOutput m = do
res <- runMachineT m
case res of
Stop -> return Nothing
Yield o r -> return $ Just (o, r)
Await _ (Const ab) _ -> absurd ab -- Unreachable
-- Run a model without input until it either produces an
-- output or stops. If the model produces output,
-- both that output and the stepped model are produced.
-- The stepped machine does not accept input. Note that
-- it is impossible to use SourceT here, at least directly,
-- as that would be impredicative.
runTFirstOutput' :: Monad m => MachineT m k o -> m (Maybe (o, AltSourceT m o))
runTFirstOutput' = runAltSourceTFirstOutput . machineTtoAltSourceT
-- Run a model without input until it either produces an
-- output or stops. If the model produces output,
-- both that output and the stepped model are produced.
-- The stepped machine may accept new input, which may or
-- may not make sense.
runTFirstOutput :: Monad m => MachineT m k o -> m (Maybe (o, MachineT m k o))
runTFirstOutput m = do
res <- runMachineT m
case res of
Stop -> return Nothing
Yield o r -> return $ Just (o, r)
Await _ _ r -> runTFirstOutput r
-- Run a model until it either produces output or stops.
-- If the model produces output, only the output is revealed;
-- the model cannot be resumed.
runTFirst :: Monad m => MachineT m k o -> m (Maybe o)
runTFirst = liftM (fmap fst) . runTFirstOutput'
-- Run a model producing elements in some semigroup; accumulate
-- them.
runTS :: (Semigroup o, Monad m) => MachineT m k o -> m (Maybe o)
runTS m = runTFirst (m ~> fold1 (flip (<>)))
runT :: Monad m => MachineT m k o -> m [o]
runT m = runTS (fmap (: []) m) >>= maybe (return []) (return . reverse) |
Bah. The pretty idea of converting a |
It may be too late to replace it, but
runT
doesn't seem to be good for much other than debugging. I suspect the most sensible general purpose version isrunT
could be written in terms ofrunTS
in a few different ways, either first mapping(:| [])
over it and then reversing the result, or doing some trick or other withEndo
; then at the endMaybe (NonEmpty a)
gets turned into[a]
.runTS
itself can be defined in terms offold1
and an even more basic machine runner that runs a machine until it produces an output, then stop it. Return that output; if the machine stopped with no output, returnNothing
.The text was updated successfully, but these errors were encountered: