Возможно ли сохранить haskell "оперативное" или "бесплатное монадное" продолжение на диск?
У меня есть несколько простых примитивных операций, например:
В случае оперативной монады:
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
Или в случае свободной монады:
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:
... функциональность может быть использована для оптимизации программ путем запоминания (при разных запусках программ) и для проверки выполнения программ в выбранных местах. Оба использования иллюстрируются в наборе слайдов, связанном выше.
( Слайды, о которых он упоминает, я думаю.)
Ограничением этого подхода является то, что не все типы данных могут (или должны!) Быть сериализованы, особенно изменяемые типы, такие как IORef
, MVar
и относящиеся к STM типы, и иногда они заканчиваются группами и замыканиями, приводящими к исключениям во время выполнения.
Кроме того, библиотека полагается на то, что сериализованное продолжение используется тем же двоичным файлом, который его создал, что может или не может быть реальной проблемой для вашего приложения.
Таким образом, вы можете получить более или менее то, что вы хотите, с немного ограниченным и сложным подходом, как packman
или вы можете написать свою собственную пользовательскую логику, которая сериализует пользовательский тип и от него, который захватывает всю информацию, которая вас интересует.