2017-03-03 11 views
2

모나드 트랜스포머를 사용하여 작가 모나드를 두 번 중첩 시키려고합니다. 내가 Struct 모나드하지 Collisiontell를 사용할 필요로Writer Monad Nested Twice

import Control.Monad.Identity 
import Control.Monad.Writer 

data Struct = S Bool 

instance Monoid Struct where 
    mempty = S True 
    mappend (S a) (S b) = S (a && b) 

data Collision = C Bool 

instance Monoid Collision where 
    mempty = C False 
    mappend (C a) (C b) = C (a || b) 

type CSInt = WriterT Collision (WriterT Struct Identity) Int 

foo :: Int -> CSInt 
foo x = do (tell (S False)) ; return x 

foo 기능은 컴파일되지 않습니다 : 여기 스케치입니다. 전혀 가능합니까?

답변

3

여러 개의 유사한 레이어가있는 것은 사실 mtl 접근 방식이 암시 적으로 lift이되는 것을 의미하는 경우입니다. 따라서 lift을 명시 적으로 사용할 수 있습니다.

lift :: Writer Struct Bool -> WriterT Collision (Writer Struct) Bool 

따라서

foo x = do lift (tell (S False)) ; return x 
+0

감사합니다. 후속 질문을 할 수 있습니다. 어떻게'runWriter'와 비슷한 함수를 모두 언 래핑할지 정의 할 수 있습니다. 서명 :'runW :: CSInt -> (Int, Bool, Bool)' – krokodil

+0

'runWriter' /'runWriterT'를 사용할 수도 있고'CSInt'에서 패턴 매칭 만 할 수도 있습니다 ('WriterT'의 정의 참조). –