2013-05-14 1 views
7

현재 모나드 트랜스포머에 약간의 어려움이 있습니다. 저는 변압기를 사용하는 몇 가지 서로 다른 비 결정 론적 관계를 정의하고 있습니다. 불행하게도 효과적인 모델을 다른 모델로 명확하게 변환하는 방법을 이해하는 데 어려움을 겪고 있습니다.변압기에서의 변환

이러한 관계가 "foo"및 "bar"라고 가정합니다. "foo"가 As와 Bs를 C와 관련 있다고 가정합니다. "bar"가 Bs와 Cs를 Ds와 관련 있다고 가정합니다. 우리는 "foo"의 관점에서 "bar"를 정의 할 것입니다. 문제를 더 재미있게 만들기 위해 이러한 관계의 계산이 다른 방식으로 실패합니다. (바 관계가 푸 관계에 의존하기 때문에, 그 실패의 경우는 상위 집합입니다.) I 따라서 다음과 같은 유형의 정의를 제공합니다 :

data FooFailure = FooFailure String 
data BarFailure = BarSpecificFailure | BarFooFailure FooFailure 
type FooM = ListT (EitherT FooFailure (Reader Context)) 
type BarM = ListT (EitherT BarFailure (Reader Context)) 
내가 다음 함수 서명과의 관계를 쓸 수 있기를 기대

:

foo :: A -> B -> FooM C 
bar :: B -> C -> BarM D 

내 문제는 "바"에 대한 정의를 작성할 때, 나는 "foo는"관계에서 오류가 발생하고 적절하게 "바"공간에서 그들을 대표 할 수 있어야한다는 것입니다. 그런 일이 있기 때문에 그래서

convert :: (e -> e') -> ListT (EitherT e (Reader Context) a 
        -> ListT (EitherT e' (Reader Context) a 

심지어 EitherT에 ListT, 매핑을 실행 한 다음 ListT을 (재 조립에 의해 그 작은 짐승을 쓸 수있는 형태의 기능이 잘 될 거라고 m [A] 수 ListT ma로 변환). 그러나 이것은 ... 지저분한 것 같습니다.

내가 변압기를 작동시킬 수없고 그 아래에 물건을 넣고 일반적으로 "다시 넣을 수는없는"이유가 있습니다. 도망친 변압기가 영향을 미칠 수 있고 마술처럼 그들을 되돌릴 수는 없습니다. 그러나 위에 나와있는 convert 함수를 작성할 필요가 없도록 일부 작업을 수행하기 위해 트랜스포머 스택에 함수를 올릴 수있는 방법이 있습니까?

답변

3

나는 그것의 (거의) 정말 간단 작성하는 변환이 좋은 답변이라고 생각하고, Control.Monad.MorphControl.Monad.Trans.Either를 사용하여 :

convert :: (Monad m, Functor m, MFunctor t) 
      => (e -> e') 
      -> t (EitherT e m) b -> t (EitherT e' m) b 
convert f = hoist (bimapEitherT f id) 

약간의 문제가 ListTMFunctor의 인스턴스가 아닌 것입니다. 나는이 ListT을 보이콧 저자 생각이 doesn't follow the monad transformer laws 그것은 일반적으로 (의 일부) 변압기 스택에 자연 변환을 처리하기위한 Control.Monad.Morph에서 살펴보고, 어쨌든 유형 검사 예를

instance MFunctor ListT where hoist nat (ListT mas) = ListT (nat mas) 

을 쓰기 쉽기 때문하지만 때문이다. 스택에 함수를 "충분하게"들어 올리는 정의에 맞다고 말할 수 있습니다.

+1

그래, 나는 ListT를 거부하고 있었다. 올바른 ListT에는'pipes'를 사용하십시오. 또한 오류 패키지에서'fmapLT'를 사용하여 왼쪽 값을 수정할 수 있습니다. –

+0

나는'fmapLT'를 찾고 있었다 ...! 그러나 나는 그것이 "어느 쪽인가"였다고 맹세 할 수 있었고, 그것을 굴하지 않았다. –

+0

우수; 둘 다 고마워. 이것은 정확하게 내가 궁금해하고 있었던 것이다. :) – tvynr