Можно ли сохранить на рабочем месте продолжение haskell "operating" или "free monad" на диск?

У меня есть некоторые простые примитивные операции, например:

В случае 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), и процесс бесконечен.

Ответ 1

Как я вижу, есть две проблемы:

  • продолжения могут содержать произвольные типы данных

  • продолжения могут содержать функции (т.е. замыкания)

Особенно учитывая второе ограничение, возможно, нет простого способа сделать именно то, что вы хотите.

Обсуждение функций Может ли Haskell быть сериализовано? указывает на библиотеку под названием packman. Из Readme:

... функциональность может быть использована для оптимизации программ посредством memoisation (в разных программах) и для выполнения контрольной точки в выбранных местах. Оба примера показаны в приведенном выше наборе слайдов.

(Слайды, о которых я упоминаю, думаю.)

Ограничение этого подхода заключается в том, что не все типы данных могут (или должны!) быть сериализованы, в частности изменяемые типы, такие как IORef, MVar и связанные с STM типы, а иногда они оказываются в трюках и замыканиях приводя к исключениям времени выполнения.

Кроме того, библиотека полагается на последовательное продолжение, которое обрабатывается тем же двоичным файлом, который создал его, что может быть или не быть реальной проблемой для вашего приложения.

Таким образом, вы можете получить более или менее то, что хотите, с небольшим ограниченным и сложным подходом, например packman, или вы можете написать свою собственную логическую логику, которая сериализуется в пользовательский тип и из него, который захватывает всю интересующую вас информацию.