2016-09-01 1 views
10

Ich habe einige einfache Grundoperationen, zum Beispiel:Ist es möglich, Haskell "Operational" oder "Free Monad" Fortsetzung auf der Festplatte zu speichern?

Bei operational Monade:

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 

oder bei free Monade:

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

Einfache Aktion in beiden gleich ist Fälle, zum Beispiel:

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

Meine Frage ist: Ist es möglich, den Prozess (proc1) so zu interpretieren, dass eine Fortsetzung in bestimmten Schritten auf die Festplatte serialisiert und dann bei der nächsten Programmausführung wiederhergestellt wird? Könnten Sie bitte ein Beispiel geben?

Wenn es nicht möglich ist, was wäre die nächste Problemumgehung?

Ich möchte das Programm nur starten, wenn die nächste Eingabe verfügbar ist, die Fortsetzung der Eingabe anwenden, dann bis zum nächsten "getInput" interpretieren und beenden.

Ich könnte mir vorstellen, das Szenario alle Eingaben zu protokollieren und sie dann wiederzugeben, um das System in den gleichen Zustand zu bringen, bevor Sie fortfahren, aber in diesem Fall würde das Protokoll unbegrenzt wachsen. Ich konnte keine Möglichkeit finden, das Log im Interpreter zu kampieren, da es keine Möglichkeit gibt, Fortsetzungen zu vergleichen (keine EQ-Instanz) und der Prozess unendlich ist.

+3

Nicht so, ich denke nicht (obwohl es möglich ist, dass einige GHC-Specials für verteilte Datenverarbeitung in der Lage sein kann, es zu tun — habe ich nie in diese gegraben). Der beste Standardansatz ist wahrscheinlich, die Bequemlichkeit und Allgemeinheit von Haskells "Monad" -Klasse für Ihre eigene benutzerdefinierte Version zu tauschen, die Funktionen in einer abstrakten Sprache darstellt, die Sie interpretieren können. – dfeuer

Antwort

5

Wie ich es sehe, gibt es zwei Probleme:

  • Fortsetzungen können beliebige Datentypen enthalten

  • Fortsetzungen können Funktionen (zB Verschlüsse) enthalten

Besonders angesichts der zweite Einschränkung, es gibt wahrscheinlich keine einfach Weg zu tun genau was du willst.

Die Diskussion auf Can Haskell functions be serialized? verweist auf eine Bibliothek mit der Bezeichnung packman. Aus der Readme-Datei:

... die Funktionalität kann verwendet werden, um Programme durch Memoisierung (über verschiedene Programmläufe hinweg) zu optimieren und die Programmausführung an ausgewählten Stellen zu überprüfen. Beide Verwendungen sind beispielhaft in dem oben verlinkten Objektträgersatz dargestellt.

(The slides es erwähnt, glaube ich.)

Die Einschränkung dieses Ansatzes ist, dass nicht alle Arten von Daten (oder sollte!) Serialisiert werden, insbesondere änderbare Typen wie IORef, MVar und STM-verwandte Typen, und manchmal enden diese in Thunks und Closures, die zu Laufzeitausnahmen führen.

Zusätzlich stützt sich die Bibliothek auf die serialisierte Fortsetzung, die von der gleichen Binärdatei übernommen wird, die es erstellte, die möglicherweise ein echtes Problem für Ihre Anwendung sein kann oder nicht.

So können Sie mehr oder weniger bekommen, was Sie wollen mit einem leicht begrenzten und komplexen Ansatz wie packman oder Sie können Ihre eigene Logik schreiben, die zu und von einem benutzerdefinierten Typ serialisiert, der alle Informationen erfasst, die Ihnen wichtig sind.

Verwandte Themen