2016-09-01 13 views
10

У меня есть некоторые простые примитивные операции, например:Можно ли сохранить haskell «операционная» или «свободная монада» на диск?

В случае operational монады:

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 монады:

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

+3

Не так, я не думаю (хотя возможно, что некоторые специальные предложения GHC для распределенных вычислений могут это сделать — Я никогда не врывался в них). Лучший стандартный подход, вероятно, заключается в том, чтобы обменять удобство и общность класса Haskell 'Monad' для вашей собственной версии, которая представляет функции на некотором абстрактном языке, который вы можете интерпретировать. – dfeuer

ответ

5

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

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

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

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

Обсуждение на Can Haskell functions be serialized? указывает на библиотеку под названием packman. Из Readme:

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

(The slides он упоминает, я думаю.)

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

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

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