ExceptT a (StateT A M)
、具体的なタイプはA
、モナドM
とし、それらを新しいカスタムモナドにまとめます。モナドをきれいにする - モナド変圧器を新しいタイプのモナドに応用すること
まず私はStateT A M
その他のコンテキストで頻繁に表示されますので、私はそれだけではモナドM1
で、その後M2
へExceptT a M1
をラップすることをラップするのがベストだろうことを決めたことを確認しました。
所望の特性は、(それがMyMonadClass
呼ばれると仮定することができます)M1
とM2
MonadState
のインスタンスとM
のクラスを作ることです。 M2
もMonadError
のインスタンスにする必要があります。
まず私は、単純な型シノニムによって開始:
type MyState = StateT A M
type MyBranch a = ExceptT a MyState
その後、私は私が最初のインスタンス(インスタンスを実行せずに)宣言し、私が最初に捕まってしまったのthatsをスケッチだろうと思いました。 instance MonadState A (MyState)
は正しい構文ではないようです。私はnewtype MyState' a = StateT a M
を作成してからtype MyState = MyState A
を作成しなければならないと思った。
しかし、同義語をnewtype
宣言に変換すると、StateT A M
とExceptT ...
タイプへの接続が失われ始めました。
newtype MyState' s a = MyState' { runMyState :: s -> (s, a) }
type MyState = MyState' A
newtype MyBranch e a = MyBranch { runMyBranch :: MyState (Either e a) }
すでに実装されているトランスが消えてしまったので、あまり意味のないことをしようとしていると思います。だから私の質問です:どのように正しく1つは、不必要な持ち上げを避けるために物事を明確かつ組織されたままにすることができます下層にアクセス可能にする新しい複合モナドにこのような行動をラップするでしょう。
に
MyBranchT Identity
や関数の型シノニムを作ってあげる、これは素晴らしい答えです、ありがとうございました。 'GeneralizedNewtypeDeriving'のような言語拡張機能を使わなくても何とかできますか? – jakubdaniel@JakubDanielもちろん、すべてのインスタンスを手作業で書くことができます。しかし、あなたはしたくない(そしておそらくそれを混乱させるでしょう)、したがって 'GeneralizedNewtypeDeriving'。 – Cirdec
GHCiで ':set -ddump-deriv'コマンドを実行した実際のコードを見るには、GHCが寛容に書いたコードをすべて表示します。 'data AB = A | Bを導出するEq'ダンプ 'インスタンスGHC.Classes.Eq Ghci5.ABここで(GHC.Classes。==)Ghci5.A Ghci5.A = GHC.Types.True; (GHC.Classes。==)Ghci5.B Ghci5.B = GHC.Types.True; (GHC.Classes。==)_ _ = GHC.Types.False' –