是否可以将 haskell "operational" 或 "free monad" 继续存储到磁盘?

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

我有一些简单的原始操作,例如:

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

或者在 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 ()

两种情况的简单操作是一样的,例如:

proc1 :: Process ()
proc1 = forever $ do
    a <- getInput
    b <- getInput
    dump $ a ++ b
    dump $ b ++ a

我的问题是:是否可以这样解释进程 (proc1),即某个步骤的延续序列化到磁盘,然后在下一个程序中恢复执行?能举个例子吗?

如果不可能,最接近的解决方法是什么?

我只想在下一个输入可用时启动程序,对输入应用延续,然后解释直到下一个 "getInput" 并退出。

我可以想象这样的场景:记录所有输入,然后重播它们以使系统在继续之前达到相同状态,但在这种情况下,日志将无限增长。我找不到任何方法来在解释器中记录日志,因为不可能比较延续(没有 EQ 实例)并且过程是无限的。

在我看来,有两个问题:

  • continuations 可以包含任意数据类型

  • continuations 可以包含函数(即闭包)

特别是考虑到第二个限制条件,可能没有容易的方法来完全您想要的。

关于Can Haskell functions be serialized? points to a library called packman的讨论。来自自述文件:

...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 它提到了,我想。)

这种方法的局限性在于并非 所有 类型的数据都可以(或应该!)序列化,尤其是可变类型,如 IORefMVar 和 STM 相关的类型,有时这些最终会导致运行时异常的 thunk 和闭包。

此外,该库依赖于由创建它的同一二进制文件占用的序列化延续,这对您的应用程序来说可能是也可能不是真正的问题。

因此,您可以通过 packman 等稍微受限和复杂的方法或多或少地获得您想要的东西,或者您可以编写自己的自定义逻辑,在捕获所有信息的自定义类型之间进行序列化你关心。