I have some simple primitive operations, for example:
In case of operational monad:
import Control.Monad.Operational
type Process a = Program ProcessI a
data ProcessI a where
GetInput :: ProcessI String
Dump :: String -> ProcessI ()
getInput :: Process String
getInput = singleton GetInput
dump :: String -> Process ()
dump = singleton . Dump
Or in case of free monad:
import Control.Monad.Free
type Process = Free ProcessF
data ProcessF a
= GetInput (String -> a)
| Dump String a
deriving (Functor)
getInput :: Process String
getInput = liftF $ GetInput id
dump :: String -> Process ()
dump s = liftF $ Dump s ()
Simple action is the same in both cases, for example:
proc1 :: Process ()
proc1 = forever $ do
a <- getInput
b <- getInput
dump $ a ++ b
dump $ b ++ a
My question is: Is it possible to interpret the process (proc1) in such a way that a continuation in certain step is serialized to disk, then restored during the next program execution? Could you please give an example?
If it's not possible, what would be the closest workaround?
I would like to start the program only when the next input is available, apply the continuation the the input, then interpret until next "getInput" and exit.
I could imagine the scenario to log all inputs, then replay them to get the system to the same state before proceeding, but in this case, the log would grow without limit. I could not find any way to campact the log in the interpreter since there is no possibility to compare continuations (no EQ instance) and the process is infinite.
Monad
class for your own custom version that represents functions in some abstract language you can interpret. – dfeuer