Писатель Монада Вложенный Дважды
Я пытаюсь вложить монаду писателя дважды, используя Монадные Трансформеры. Вот эскиз:
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
функция не компилируется, так как мне нужно использовать tell
на Struct
монада, не Collision
, Это вообще возможно?
1 ответ
Решение
Наличие нескольких одинаковых слоев на самом деле является одним из случаев, когда mtl
подход, который призван сделать lift
неявный, имеет проблемы, как вы упомянули. Так что вы можете использовать lift
в явном виде.
lift :: Writer Struct Bool -> WriterT Collision (Writer Struct) Bool
таким образом
foo x = do lift (tell (S False)) ; return x