2017-01-22 11 views
5

StateT g (Either E) TExceptT E (StateT g Identity) Tに変換するには?内外のモナドを交換する

恐らく、traversehoistのいくつかの組み合わせが役に立つでしょう。

+2

'StateT g(Either e)t'が失敗すると、状態を提供しません。対応する「ExceptT e(StateT g Identity)tは何をすべきですか? – danidiaz

+0

正確な定義を思い出すことはできませんが、状態によっては最初のモナドが失敗することはありません(たとえば、状態が偶数の場合)。 – chi

答えて

9

You can't exchange an arbitrary pair of monads。しかし、これらの2つの特定のモナドを交換することができます。それらのモナド変圧器の定義にnewtypeを展開するのが最も簡単です。あなたの最初の型の式でnewtype Sを拡大

考える

newtype StateT s m a = StateT { runStateT :: s -> m (s, a) } 

newtype ExceptT e m a = ExceptT { runExceptT :: m (Either e a) } 

は、第二のために我々が得るのに対し、私たちに同型

StateT s (Either e) a <-> s -> Either e (s, a) 

を与える

ExceptT e (StateT s Identity) a <-> s -> (s, Either e a) 

Either e (s, a)にはsが含まれていても含まれていなくてもかまいませんが、(s, Either e a)は常に存在します。さて、関数内でタプルを入れるだけで後者から前者に行くことができますが、逆にいくらかのドメイン固有の推論が必要です:計算がエラーを投げた場合、状態をそのままキャッチャーに渡す必要がありますエラーのこれは正しいことですか?それはむしろ議論の余地があります。

stateTEitherToExceptTState :: (s -> Either e (s, a)) -> (s -> (s, Either e a)) 
stateTEitherToExceptTState f s = 
    case f s of 
     Left e -> (s, Left e) 
     Right sa -> fmap Right sa 
+1

私は 'stateTEitherToExceptTState'が有効なモナドモーフィズムではないと思います。 'm 'が失敗しないアクションであり、' f'が常に失敗する 'fle'がある場合、' morph(m >> = f) 'は' morph m> = morphに等しくありません。 f 'である。 – danidiaz

関連する問題