2017-09-11 12 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' ("running"사물의 전체적인 개념은 모나드 트랜스포머 컨셉의 일부조차도 아니다)가 주어진 것을 수행하려는 일반적인 방법은 없습니다. 대답과 같은 특수 기능을 사용할 수 있지만 일반 솔루션은 없습니다. – Cubic

답변

3

이 특정한 경우에 단순한는 MFunctor 인스턴스를 사용하는 것 같다 접근 ExceptT eWriterT w 변압기의 :

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) 

State s = StateT s Identity 때문에, 약간의 일반화는 위의 즉각적인이다.

+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