2016-09-01 11 views
10

Mam kilka prostych operacji prymitywnych, na przykład:Czy możliwe jest przechowywanie na dysku haskela "operacyjnego" lub "wolnego monada"?

W przypadku operational monady:

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 

lub w przypadku free monady:

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() 

Proste działania jest taka sama w obu przypadki, na przykład:

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

Moje pytanie brzmi:: Czy można zinterpretować proces (proc1) w taki sposób, aby kontynuacja w pewnym etapie została przekształcona na dysk w postaci szeregowej, a następnie przywrócona podczas następnego uruchomienia programu? Czy mógłbyś podać przykład?

Jeśli nie jest możliwe, jakie byłoby najbliższe obejście tego problemu?

Chciałbym uruchomić program tylko wtedy, gdy następne wejście jest dostępne, zastosować kontynuację wejścia, następnie interpretować do następnego "getInput" i wyjść.

Mogę sobie wyobrazić scenariusz do rejestrowania wszystkich danych wejściowych, a następnie powtórzyć je, aby system działał w tym samym stanie przed kontynuowaniem, ale w tym przypadku dziennik będzie rósł bez ograniczeń. Nie mogłem znaleźć żadnego sposobu na zapisanie dziennika w tłumaczu, ponieważ nie ma możliwości porównania kontynuacji (bez instancji EQ), a proces jest nieskończony.

+3

Nie tak, nie sądzę (choć jest możliwe, że niektóre specjalizacje GHC do obliczeń rozproszonych mogą to zrobić — Nigdy w nich nie zagłębiałem). Najlepszym standardem jest prawdopodobnie wymienienie wygody i ogólności klasy 'Monad' Haskella dla twojej własnej wersji niestandardowej, która reprezentuje funkcje w jakimś abstrakcyjnym języku, który możesz zinterpretować. – dfeuer

Odpowiedz

5

Jak ja to widzę, istnieją dwa problemy:

  • kontynuacje mogą zawierać dowolne typy danych

  • kontynuacje mogą zawierać funkcje (tj zamknięć)

Zwłaszcza biorąc pod uwagę drugie ograniczenie, prawdopodobnie nie jest to łatwy sposób na wykonanie dokładnie czego chcesz.

Dyskusja na temat Can Haskell functions be serialized? wskazuje na bibliotekę o nazwie packman. Z pliku Readme:

... Funkcję tę można wykorzystać do optymalizacji programów poprzez zapamiętywanie (w różnych programach) oraz do wykonywania programów punktów kontrolnych w wybranych miejscach. Oba zastosowania są przedstawione na powyższym zestawie slajdów.

(The slides wspomina, jak sądzę).

Ograniczeniem tej metody jest to, że nie wszystkie typy danych może (lub powinien!) Być w odcinkach, zwłaszcza Zmienne typy jak IORef, MVar i Są to typy związane z STM, a czasem kończą się one w partiach i zamknięciach prowadzących do wyjątków w czasie wykonywania.

Dodatkowo, biblioteka korzysta z kontynuacji szeregowej, która została podjęta przez ten sam plik binarny, który ją utworzył, co może, ale nie musi być prawdziwym problemem dla twojej aplikacji.

Dzięki temu można uzyskać mniej lub bardziej to, co się chce, przy nieco ograniczonym i złożonym podejściu, takim jak packman, lub można napisać własną niestandardową logikę, która przekształca się do postaci niestandardowej i przechwytuje wszystkie informacje, na których zależy.

Powiązane problemy