실제로 두 가지 해결책이 있습니다.
첫 번째 해결 방법은 Daniel Wagner가 제안한 것입니다. 두 개의 기본 모나드를 수정하여 동일한 Left
유형을 사용합니다. 예를 들어, 둘 다 ByteString
으로 정규화 할 수 있습니다.이렇게하려면, 우리가 처음 ByteString
의 pack
기능을 가지고 :
다음
pack :: String -> ByteString
우리가이 EitherT
의 왼쪽 값에 일을 들어 올려 것은 :
import Control.Error (fmapLT) -- from the 'errors' package
fmapLT pack :: (Monad m) => EitherT String m r -> EitherT ByteString m r
이제 우리는 필요로하는 변환을하는 대상에 hoist
를 사용 Consumer
의 기본 모나드 :
hoist (fmapLT pack)
:: (Monad m, Proxy p)
=> Consumer p a (EitherT String m) r -> Consumer p a (EitherT ByteString m) r
지금 당신은 당신의 소비자가 무서운 구성 할 수 그들은 같은 기본 모나드를 가지고 있기 때문에 당신의 프로듀서와 함께 ctly.
두 번째 해결책은 Daniel Diaz Carrete가 제안한 해결책입니다. 대신 두 개의 파이프를 EitherT
레이어를 모두 포함하는 공통 모나 드 변압기 스택에 동의하게 만듭니다. 두 레이어를 중첩 할 순서를 결정하기 만하면됩니다.
EitherT ByteString
변압기 외부에 EitherT String
변압기를 겹쳐 놓았다고 가정 해 봅시다. 그게 당신의 최종 목표 모나드 변압기 스택이 될 것이라고 의미 :
(Proxy p) => Session (EitherT String (EitherT ByteString p)) IO r
지금 당신은 변압기 스택을 대상으로하여 파이프의 양쪽을 촉진 할 필요가있다. 당신의 Consumer
를 들어
, 당신은 당신이 마지막 모나드 변압기 스택과 일치 할 경우 EitherT String
사이 IO
에 EitherT ByteString
레이어를 삽입해야합니다. 레이어를 만드는 것은 쉽습니다. 을 사용하면되지만 프록시 모나드 변환기와 EitherT String
모나드 변압기를 건너 뛸 필요가 있으므로 hoist
을 두 번 사용하도록 두 특정 레이어 사이를 들어야합니다.
당신의
Producer
를 들어
hoist (hoist lift) . consumer
:: Proxy p =>() -> Consumer p a (EitherT String (EitherT ByteString IO))()
, 당신은 당신이 마지막 모나드 변압기 스택과 일치 할 경우 프록시 모나드 변압기와 EitherT ByteString
변압기 사이에 EitherT String
레이어를 삽입해야합니다. 다시 말하면 레이어를 만드는 것이 쉽습니다. lift
을 사용하기 만하지만 두 개의 특정 레이어 사이에서 그 리프트를 타겟팅해야합니다. 당신은 단지 hoist
,하지만 당신은 단지 올바른 자리에 잠시 멈춰서는 lift
에 프록시 모나드 변압기 건너 뛸 필요가 있기 때문에이 시간 당신은 한 번만 사용 :
hoist lift . producer
:: Proxy p =>() -> Producer p a (EitherT String (EitherT ByteString IO)) r
지금 당신의 생산자와 소비자가 같은 모나드 변압기가 스택하고 직접 작성할 수 있습니다.
이제 0120-lift
이 프로세스가 "올바른 작업"을 수행하고 있는지 궁금 할 수 있습니다. 대답은 '예'입니다. 카테고리 이론의 마법의 일부는 lift
을 사용하여 "빈 모나드 변압기 레이어"를 정확히 삽입한다는 의미를 정확히 정의 할 수 있으며, 마찬가지로 hoist
을 사용하여 "두 모나드 변압기 사이에서 무언가를 목표로 삼는다"는 의미를 엄격하게 정의 할 수 있습니다 이론적으로 영향을받은 몇 가지 법칙을 명시하고 lift
및 hoist
이 해당 법을 준수하는지 확인합니다.
우리가 이러한 법칙을 만족하면 정확히 lift
과 hoist
이하는 모든 핵심적인 세부 사항을 무시할 수 있습니다.범주 이론은 모나드 변압기와 공간 코드 사이에 공간적으로 "리프트를 삽입하는"면에서 우리가 생각하는 매우 높은 추상화 수준에서 작업 할 수있게 해줌으로써 우리의 공간적 직감을 마술처럼 정확하게 해석합니다.
내 생각에 첫 번째 해결 방법은 단일 EitherT
레이어에서 생산자와 소비자간에 오류 처리 기능을 공유 할 수 있기를 원할 것입니다.
타입 추론기를 사용하여 'runProxy $ hoist lift'를 입력하여'session'을 확인했습니다. 생산자> -> 호이스트 (호이스트 리프트). 소비자 '. 나는 또한'EitherT e'를위한'MFunctor' 인스턴스를 만들어야했습니다 :'instance (EitherT e) where hoist nat = mapEitherT nat'. 나는 왜 이것이 효과가 있는지 아직 알지 못하기 때문에 질문을 끝내지 않을 것입니다. –