Aufräumen von Monaden - Anwendung eines Monodentransformators in newtype monad umwandeln

8

Ich versuche, z.B. ExceptT a (StateT A M) , für einige konkrete Typen A und monad M , und schliesse sie in meine neuen benutzerdefinierten Monaden.

Zuerst habe ich festgestellt, dass StateT A M oft in anderen Kontexten auftaucht, und daher entschied ich, dass es am besten wäre, das Ganze in eine Monade M1 einzubinden und dann ExceptT a M1 in M2 einzubinden.

Die gewünschte Eigenschaft ist M1 und M2 Instanzen von MonadState und die Klasse von M (nehmen wir an, dass es MyMonadClass heißt). Auch M2 sollte eine Instanz von MonadError sein.

Zuerst habe ich mit einfachen Synonymen angefangen:

%Vor%

Dann dachte ich, dass ich zuerst die Deklarationen der Instanz skizzieren würde (ohne die Instanz zu implementieren), und das ist, wo ich zuerst stecken geblieben bin. instance MonadState A (MyState) schien nicht die richtige Syntax zu sein. Ich dachte, ich müsste newtype MyState' a = StateT a M und dann type MyState = MyState A erstellen (Lässt keine Spracherweiterungen verwenden, wenn nicht notwendig).

Nachdem ich jedoch begonnen habe, die Synonyme in newtype declarations zu konvertieren, habe ich die Verbindung zu den StateT A M und ExceptT ... Typen verloren.

%Vor%

Jetzt sind die Transformatoren, die bereits implementiert sind, verschwunden und ich denke, ich versuche etwas zu tun, das nicht viel Sinn macht. Meine Frage ist also: Wie würde man diese Art von Verhalten korrekt in neue zusammengesetzte Monaden verpacken, die die darunterliegenden Schichten zugänglich machen, so dass man unnötiges Heben vermeidet und die Dinge klar und übersichtlich hält.

    
jakubdaniel 14.09.2015, 19:09
quelle

1 Antwort

9

Das normale Muster ist, einen neuen Typ für Ihren kompletten Transformatorstapel zu definieren.

%Vor%

Wenn es Teile des Stapels gibt, die eigene nützliche Fähigkeiten hinzufügen, definieren Sie auch neue Typen für diese Teile.

Dann verwenden Sie GeneralizedNewtypeDeriving , um Instanzen für alle verschiedenen Monad-Klassen zu erhalten.

%Vor%

Sie müssen die MonadTrans -Instanz von Hand schreiben. lift ist immer nur lift für jeden der Transformer im Stack.

%Vor%

Wenn es Teile des Stapels gibt, die sinnvolle neue Fähigkeiten X hinzufügen, würden Sie auch eine neue MonadX Klasse für diese Fähigkeiten definieren, schreiben Sie MonadX Instanzen für jedes der Monadentransformer ( StateT , ExceptT , ContT , usw.), wenn möglich, und leiten Sie die MonadX -Instanz für Ihren Transformator-Stack ( MyBranchT ) ab.

Sie werden auch normalerweise ein Synonym für MyBranchT Identity und Funktionen für runMyBranchT und runMyBranch

eingeben %Vor%     
Cirdec 14.09.2015, 19:42
quelle