Как добиться эффекта "продукта двух монадов"?
Предположим, что у нас две монады, m
и m'
. Предположим теперь, что у нас есть переменные,
-- in real problems, the restriction is some subclass MyMonad, so don't worry
-- if it 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'
? Я знаю, что это возможно со стрелками, но для монад кажется более сложным (невозможно?), Особенно при попытке написать, что должен делать 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
Да, этот тип - монада. Ключ просто передать оба результата в 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
доступен в пакете monad-products под названием Product
.