I want to create an automata type with a type like this:
newtype Auto i o = Auto {runAuto :: i -> (o, Auto i o)}
I know this is the type of the Automata arrow, but I'm not looking for an arrow. I want to make this a monad, so presumably its going to have a type like
newtype Auto i o a = ???? What goes here?
with a function like this:
yield :: o -> Auto i o i
So when I call "yield" from within the Auto monad the "runAuto" function returns a pair consisting of the argument to "yield" and the continuation function. When the application program calls the continuation function the argument is then returned within the monad as the result of "yield".
I know this is going to require some flavour of continuation monad, but despite having wrangled with continuations in the past I can't see how to code this one.
I also know that this rather resembles Michael Snoyman's Conduit monad, except that he splits up "yield" and "await". This monad has to have exactly one output for every input.
Background: I'm writing some code that responds to GUI events in a complicated way. Rather than turning this into a hand-coded state machine I'm hoping to be able to write code that accepts a series of inputs in return for yielding updates to the screen as the user interaction progresses.
Edit
All this turned out to be subtly wrong. I wrote the code suggested by Petr Pudlák in his reply, and it seemed to work, but the "yield" operation always yielded the output from the previous yield. Which was wierd.
After much staring at the screen I finally figured out that I needed the code pasted here. The crucial difference is in the AutoF type. Compare the one below with the one proposed by Petr.
import Control.Applicative
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.State.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Free
import Data.Void
class (Monad m) => AutoClass i o m | m -> i, m -> o where
   yield :: o -> m i
data AutoF i o a = AutoF o (i -> a)
instance Functor (AutoF i o) where
   fmap f (AutoF o nxt) = AutoF o $ \i -> f $ nxt i
newtype AutoT i o m a = AutoT (FreeT (AutoF i o) m a)
   deriving (Functor, Applicative, Monad, MonadIO, MonadTrans, MonadState s)
instance (Monad m) => AutoClass i o (AutoT i o m) where
   yield v = AutoT $ liftF $ AutoF v id
runAutoT :: (Monad m) => AutoT i o m Void -> m (o, i -> AutoT i o m Void)
runAutoT (AutoT step) = do
   f <- runFreeT step
   case f of
      Pure v -> absurd v
      Free (AutoF o nxt) -> return (o, AutoT . nxt)
-- Quick test
--
-- > runTest testStart
testStart :: Int -> AutoT Int Int IO Void
testStart x = do
   liftIO $ putStrLn $ "My state is " ++ show x
   y <- liftIO $ do
      putStrLn "Give me a number: "
      read <$> getLine
   v1 <- yield $ x + y
   liftIO $ putStrLn $ "I say " ++ show v1
   v2 <- yield $ 2 * v1
   testStart v2
runTest auto = do
   putStrLn "Next input:"
   v1 <- read <$> getLine
   (v2, nxt) <- runAutoT $ auto v1
   putStrLn $ "Output = " ++ show v2
   runTest nxt