2017-03-03 42 views
2

我想用Monad變形金剛嵌套作家monad兩次。這裏是一個草圖:作家Monad嵌套兩次

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功能無法編譯,因爲我需要在Struct單子,不Collision使用tell。它有可能嗎?

回答

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'的定義)。 –