Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to store haskell "operational" or "free monad" continuation to disk?

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.

like image 992
Zoran Bošnjak Avatar asked Sep 01 '16 12:09

Zoran Bošnjak


1 Answers

As I see it, there are two problems:

  • continuations can contain arbitrary data types

  • continuations can contain functions (ie closures)

Especially given the second constraint, there's probably no easy way to do exactly what you want.

The discussion on Can Haskell functions be serialized? points to a library called packman. From the Readme:

...the functionality can be used to optimise programs by memoisation (across different program runs), and to checkpoint program execution in selected places. Both uses are exemplified in the slide set linked above.

(The slides it mentions, I think.)

The limitation of this approach is that not all types of data can (or should!) be serialized, notably mutable types like IORef, MVar and STM-related types, and sometimes these end up in thunks and closures leading to runtime exceptions.

Additionally, the library relies on the serialized continuation being taken up by the same binary that created it which may or may not be a real problem for your application.

So you can either get more or less what you want with a slightly limited and complex approach like packman or you can write your own custom logic that serializes to and from a custom type that captures all the information you care about.

like image 60
Tikhon Jelvis Avatar answered Nov 16 '22 07:11

Tikhon Jelvis