Protokollierung mit der freien Monade

8

Diese Frage bezieht sich auf diesen Artikel

Die Idee ist, eine DSL für das Manipulieren von Dateien in der Cloud zu definieren und ein Zusammensetzung von Dolmetschern, die sich um die verschiedenen Aspekte kümmern, wie z Kommunikation mit der REST-Schnittstelle und Protokollierung.

Um dies konkreter zu machen, nehmen wir an, dass wir die folgende Datenstruktur haben definiert die Bedingungen der DSL.

%Vor%

Wir definieren Funktionen zum Erstellen von CloudFiles-Programmen wie folgt:

%Vor%

Dann ist die Idee, dies in Bezug auf zwei andere DSLs zu interpretieren:

%Vor%

Ich habe es geschafft, eine natürliche Transformation von der CloudFiles DSL zur REST DSL mit folgendem Typ:

%Vor%

Dann gegeben ein Programm des Formulars:

%Vor%

Es ist möglich, das Programm mit REST-Aufrufen wie folgt zu interpretieren:

%Vor%

Das Problem kommt beim Versuch, eine Interpretation der DSL mit zu definieren protokollieren. In dem Artikel, den ich oben erwähnt habe, definiert der Autor einen Interpreter mit Typ:

%Vor%

und wir definieren einen Interpreter für Free LogF a vom Typ:

%Vor%

Das Problem ist, dass dieser Interpreter nicht in Kombination mit verwendet werden kann foldFree wie oben. Die Frage ist also, wie man ein Programm interpretiert Free CloudFilesF a mit der Funktion logCloudfilesI und interpretLog oben definiert? Im Grunde suche ich nach einer Funktion mit dem Typ:

%Vor%

Ich kann das mit dem REST DSL machen, aber ich kann es nicht usng logCloudfilesI machen.

Was ist der Ansatz, wenn in diesen Situationen freie Monaden verwendet werden? Hinweis das Problem scheint die Tatsache zu sein, dass es für den Fall der Protokollierung keine gibt bedeutender Wert können wir der Funktion in ListFiles liefern, um die Fortsetzung des Programms. In einem zweiten Artikel  Der Autor verwendet Halt jedoch Dies funktioniert nicht in meiner aktuellen Implementierung .

    
Damian Nadales 18.10.2016, 10:26
quelle

1 Antwort

6

Die Protokollierung ist ein klassischer Anwendungsfall für das Decorator-Muster.

Der Trick besteht darin, das Programm in einem Kontext zu interpretieren, der sowohl auf die Logging-Effekte als auch auf einen Basiseffekt zugreifen kann. Die Anweisungen in einer solchen Monade würden entweder Anweisungen für den Befehl oder vom Basis-Funktor protokollieren. Hier ist das Funktorkoprodukt , das im Grunde genommen " Either für Funktoren" ist.

%Vor%

Wir müssen in der Lage sein, Programme von einer Basis-freien Monade in die freie Monade eines Koprodukt-Funktors zu injizieren.

%Vor%

Jetzt haben wir genug Struktur, um den Logging Interpreter als Dekorator um einen anderen Interpreter zu schreiben. decorateLog verschachtelt die Protokollierungsbefehle mit Anweisungen von einer beliebigen freien Monade und delegiert die Interpretation an eine Funktion CloudFiles f a -> Free f a .

%Vor%

So decorateLog interpretCloudWithRest :: CloudFilesF a -> Free (LogF :+: RestF) a ist ein Interpreter, der ein Programm ausgibt, dessen Befehlssatz aus Anweisungen von LogF und RestF besteht.

Jetzt müssen wir nur noch einen Interpreter (LogF :+: RestF) a -> IO a schreiben, den wir aus interpLogIO :: LogF a -> IO a und interpRestIO :: RestF a -> IO a erstellen.

%Vor%

So foldFree interpLogRestIO :: Free (LogF :+: RestF) a -> IO a wird die Ausgabe von decorateLog interpretCloudWithRest in der IO Monade ausführen. Der gesamte Compiler wird als foldFree interpLogRestIO . foldFree (decorateLog interpretCloudWithRest) :: Free CloudFilesF a -> IO a geschrieben.

In seinem Artikel geht de Goes (ha ha) einen Schritt weiter und baut diese Coprodukt-Infrastruktur mit Prismen . Dies vereinfacht die Zusammenfassung über den Befehlssatz.

Der USP der extensible-effects -Bibliothek ist, dass es all das Gerangel mit Funktor-Coprodukten für Sie automatisiert. Wenn du die kostenlose Monadroute verfolgst (persönlich bin ich nicht so begeistert wie de Goes), dann würde ich extensible-effects empfehlen, anstatt dein eigenes Effektsystem zu rollen.

    
Benjamin Hodgson 18.10.2016, 14:12
quelle