如何实现“两个单子的产品”效果?

时间:2012-01-26 02:34:12

标签: haskell monads

假设我们有两个monad,mm'。现在,假设我们有变量,

-- in real problems, the restriction is some subclass MyMonad, so don't worry
-- if it's the case here that mx and f must essentially be pure.
mx :: Monad m'' => m'' a
f :: Monad m'' => a -> m'' b

有没有办法创建类似于产品m x m'的任何内容?我知道这对Arrows来说是可能的,但对monad来说似乎更复杂(不可能?),尤其是在尝试编写mx >>= f应该做的事情时。

要看到这一点,请定义

data ProdM a = ProdM (m a) (m' a)
instance Monad ProdM where
    return x = ProdM (return x) (return x)

但现在,当我们定义mx >>= f时,不清楚mx中哪个值传递给f

    (ProdM mx mx') >>= f
        {- result 1 -} = mx >>= f
        {- result 2 -} = mx' >>= f

我希望(mx >>= f) :: ProdM((mx >>= f) :: m) x ((mx >>= f) :: m')同构。

1 个答案:

答案 0 :(得分:18)

是的,这种类型是monad。关键是将两个结果传递给f,并且只保留结果中的匹配字段。也就是说,我们保留传递mx结果的结果中的第一个元素,以及传递mx'结果的结果中的第二个元素。实例看起来像这样:

instance (Monad m, Monad m') => Monad (ProdM m m') where
  return a = ProdM (return a) (return a)
  ProdM mx mx' >>= f = ProdM (mx >>= fstProd . f) (mx' >>= sndProd . f)
    where fstProd (ProdM my _) = my
          sndProd (ProdM _ my') = my'
名称为ProdM的{​​{3}}包中提供了

Product