Writer Monad 嵌套两次

Writer Monad Nested Twice

我正在尝试使用 Monad Transformers 嵌套 writer 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 monad 上使用 tell,而不是 Collision。有可能吗?

具有多个相似层实际上是 mtl 方法的一种情况,这意味着使 lift 隐含,正如您提到的那样存在问题。所以你可以明确地使用lift

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

因此

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