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.
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.
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.
Sie müssen die MonadTrans
-Instanz von Hand schreiben. lift
ist immer nur lift
für jeden der Transformer im Stack.
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
Tags und Links haskell newtype state-monad monad-transformers lifting