Писатель Монада Вложенный Дважды

Я пытаюсь вложить монаду писателя дважды, используя Монадные Трансформеры. Вот эскиз:

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
Другие вопросы по тегам