2017-09-11 8 views
1

mtlのモナド・スタックがあるとします。 ExceptT String (WriterT String (State s a))、外側のモナドをアンラップする必要なしに内部状態のモナドをどのように評価できますか?モナド・トランス・スタック内のevalState

have :: ExceptT String (WriterT String (State s)) a 
f :: State s a -> a 

want :: ExceptT String (WriterT String Identity) a 

私はrunWriterT続いrunExceptTを呼び出し、その後、結果を再梱包してこれを行うことができますが、これを達成するために間違った方法のように思えます。モナド変圧器スタックはそれ自身の全体のモナドとして扱われるため


は限り私が試したとして、fmapまたは類似のようなものは動作しません。どちらの

split :: (MonadTrans s, Monad t) => (s t) a -> s (t a) 

私は、この機能を発見していないか、ソリューションが完全に動作が異なります:私は何に必要なのは、このような「スプリット」への機能モナド変圧器スタックです。

+2

できません。すべての変圧器が追加するのは 'lift :: m a - > t m a'です。 'Monad'と' MonadTrans'(モナドトランスのコンセプトの一部でさえも、 "実行中の"ものという概念の全体の概念)を与えて、あなたがしようとしていることを実装する一般的な方法はありません。答えのような特殊な機能を持つことはできますが、一般的な解決策はありません。 – Cubic

答えて

3

この特定のケースでは、最も簡単なようだアプローチがMFunctorインスタンスを使用することですExceptT eWriterT wトランス:State s = StateT s Identityので

import Control.Monad.Morph 

floop :: Monad m 
     => s 
     -> ExceptT e (WriterT w (StateT s m)) a 
     -> ExceptT e (WriterT w m) a 
floop s = hoist (hoist $ flip evalStateT s) 

、上記わずかな一般化は、即時です。

+0

'ホイスト 'は私が探していたものでした。 – ThreeFx

5

私はあなたのsplitとして一般として何を認識してないんだけど、map...T機能を使用すると、明示的な操作を防ぐことができます:

have :: ExceptT String (WriterT String (State s)) a 
f :: State s a -> a 

want :: ExceptT String (WriterT String Identity) a 
want = mapExceptT (mapWriterT (return . f)) have 
関連する問題