Ich versuche, z.B. ExceptT a (StateT A M)
, für einige Betontypen A
und Monad M
, und wickeln Sie sie in meine neuen benutzerdefinierten Monaden ein.Aufräumen von Monaden - Anwendung eines Monodentransformators in Newtype-Monade umwandeln
Zuerst habe ich festgestellt, dass StateT A M
erscheint oft in anderen Zusammenhängen und so habe ich beschlossen, es wäre am besten, dass allein in einer Monade M1
zu wickeln und dann ExceptT a M1
in M2
wickeln.
Die gewünschte Eigenschaft ist M1
und M2
Instanzen MonadState
und die Klasse von M
zu machen (kann davon ausgehen, es MyMonadClass
genannt wird). Auch M2
sollte eine Instanz von MonadError
sein.
Zuerst habe ich angefangen von einfachen Typ Synonyme:
type MyState = StateT A M
type MyBranch a = ExceptT a MyState
dann dachte ich, dass ich zum ersten Mal der Instanzdeklarationen skizzieren würde (ohne die Instanz Umsetzung) und das ist, wo ich zum ersten Mal fest. 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 wo nicht notwendig).
Doch sobald ich die Synonyme in newtype
Erklärungen begann Umwandlung begann ich die Verbindung zu den StateT A M
und ExceptT ...
Arten zu verlieren.
newtype MyState' s a = MyState' { runMyState :: s -> (s, a) }
type MyState = MyState' A
newtype MyBranch e a = MyBranch { runMyBranch :: MyState (Either e a) }
Jetzt sind die Transformatoren, die bereits umgesetzt 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 Schichten darunter zugänglich machen, so dass man unnötiges Heben vermeidet und die Dinge klar und gut organisiert hält.
Vielen Dank, diese Antwort eine große ist. Kann ich irgendwie auf Spracherweiterungen wie "GeneralizedNewtypeDeriving" verzichten? – jakubdaniel
@JakubDaniel Sicher kannst du alle Instanzen von Hand schreiben. Aber du willst nicht (und wirst wahrscheinlich einen vermasseln), also 'GeneralizedNewtypeDeriving'. – Cirdec
Um den eigentlichen Code zu sehen, der abgeleitet wird, führen Sie den Befehl ': set -ddump-deriv' in GHCi aus, er zeigt Ihnen den ganzen Code, den GHC großzügig für Sie schreibt. 'Daten AB = A | B Ableiten von Eq 'Dumps' Instanz GHC.Classes.Eq Ghci5.AB wobei (GHC.Classes. ==) Ghci5.A Ghci5.A = GHC.Types.True; (GHC.Classes. ==) Ghci5.B Ghci5.B = GHC.Types.Thru; (GHC.Classes. ==) _ _ = GHC.Types.False' –