Ich baue gerade eine neue API und eine der folgenden Funktionen ist:
%Vor% Ich versuche, das Tracer
in eine Monade zu verschieben und mir eine Signatur zu geben, die mehr wie
Die Implementierung von inSpan
verwendet bracket
, was bedeutet, dass ich zwei Hauptoptionen habe:
oder
%Vor% Aber was sollte ich bevorzugen? Beachte, dass ich alle oben genannten Typen unter Kontrolle habe, was mich dazu bringt, mich etwas in Richtung MonadMask
zu neigen, da es IO
am Ende nicht erzwingt (das heißt, wir könnten vielleicht eine reine MonadTracer
haben) Instanz).
Gibt es noch etwas, das ich beachten sollte?
Lassen Sie uns zuerst die Optionen festlegen (wiederholen Sie dabei einige Ihrer Fragen):
MonadMask
aus der exceptions
-Bibliothek. Dies kann bei einer Vielzahl von Monaden und Transformatoren funktionieren und erfordert nicht, dass die Basismonade IO
ist. MonadUnliftIO
aus der unliftio-core
(oder unliftio
) Bibliothek. Diese Bibliothek funktioniert nur für Monaden mit IO
an ihrer Basis und die isomorph zu ReaderT env IO
ist. MonadBaseControl
aus der monad-control
-Bibliothek. Diese Bibliothek benötigt IO
an der Basis, erlaubt aber nicht-ReaderT. Jetzt die Kompromisse. MonadUnliftIO
ist die neueste Ergänzung des Fray und hat die am wenigsten entwickelte Bibliotheksunterstützung. Dies bedeutet, dass zusätzlich zu den Beschränkungen, welche Monaden Instanzen sein können, viele gute Instanzen noch nicht geschrieben wurden.
Die wichtige Frage ist: Warum macht MonadUnliftIO
diese scheinbar willkürliche Anforderung um ReaderT
- ähnliche Dinge? Dies dient dazu, Probleme mit dem verlorenen monadischen Zustand zu verhindern. Zum Beispiel ist die Semantik von bracket_ (put 1) (put 2) (put 3)
nicht wirklich klar und daher lässt MonadUnliftIO
eine StateT
-Instanz nicht zu.
MonadBaseControl
lockert die Beschränkung ReaderT
und bietet eine erweiterte Bibliotheksunterstützung. Es wird auch intern als komplizierter angesehen als die anderen beiden, aber für Ihre Verwendungen sollte das eigentlich keine Rolle spielen. Und es erlaubt Ihnen, Fehler mit dem oben erwähnten monadischen Zustand zu machen. Wenn Sie bei der Verwendung vorsichtig sind, spielt dies keine Rolle.
MonadMask
ermöglicht völlig reine Transformatorstapel. Ich denke, es gibt ein gutes Argument, um die Nützlichkeit der Modellierung von asynchronen Ausnahmen in einem reinen Stack zu haben, aber ich verstehe, dass diese Art von Ansatz etwas ist, was Leute manchmal tun wollen. Im Gegenzug für das Erhalten von mehr Instanzen haben Sie immer noch die Einschränkungen in Bezug auf den monadischen Status und die Unfähigkeit, einige IO
-Steueraktionen wie timeout
oder forkIO
zu erhöhen.
Meine Empfehlung:
MonadMask
zu wählen, es ist die am besten angenommene Lösung. timeout
oder withMVar
oder etwas tun, verwenden Sie MonadBaseControl
. MonadUnliftIO
. Tags und Links haskell monad-transformers