定义嵌套 monad 的 Monad

Defining Monad of nested monads

我正在尝试为一个类型定义一个 monad 实例,其定义如下:

type Error a = Either String a
data Outer a = Outer { fromOuter :: Error (Maybe a) } 

FunctorsApplicative 类型的 Outer 实例可以定义为:

instance Functor Outer where
    f `fmap` (Outer fa) = Outer $ fmap (fmap f) $ fa 


instance Applicative Outer where
     pure = Outer . pure . pure
     (Outer l) <*> (Outer r) = Outer $ do
                             el <- l
                             er <- r
                             return $ el <*> er

但是,我正在努力定义 bind 来为这种类型定义 Monad 实例:

instance Monad Outer where
    return = pure
    (Outer l) >>= f = ??????

进一步的问题是:

如何将以上概括为

data Outer m n a = Outer { fromOuter :: m (n a) }

这个问题是hedis-simple where I am trying to define Monad instance for RedisTx

中一个问题的抽象

你的 >>= 函数的类型应该是

Outer a -> (a -> Outer b) -> Outer b

因为在某些 xOuter 值为 (Right (Just x)) 的情况下,您只有一个 a,您可以这样做:

instance Monad Outer where
  return = pure
  (Outer l) >>= f = case l of
    Left e -> Outer (Left e)
    Right Nothing -> Outer (Right Nothing)
    Right (Just x) -> f x

关于你的第二个问题,你不能。给定两个 monad MN 它们的组合 M N 不能自动变成 monad。有关详细信息,请参阅 this question