2012-01-26 9 views
11

Supponiamo di avere due monadi, m e m'. Ora, supponiamo di avere variabili,come ottenere l'effetto "prodotto di due monadi"?

-- 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 

C'è un modo per creare qualcosa di simile al prodotto m x m'? So che questo è possibile con Arrows, ma sembra più complicato (impossibile?) Per le monadi, soprattutto quando si cerca di scrivere ciò che dovrebbe fare mx >>= f.

di vedere questo, definire

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

ma ora, quando definiamo mx >>= f, non è chiaro quale valore da mx da passare al f,

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

voglio (mx >>= f) :: ProdM essere isomorfo a ((mx >>= f) :: m) x ((mx >>= f) :: m').

risposta

18

Sì, questo tipo è una monade. La chiave è semplicemente passare entrambi i risultati su f e mantenere solo il campo corrispondente dal risultato. Cioè, manteniamo il primo elemento dal risultato del superamento del risultato di mx e dal secondo elemento dal risultato del superamento del risultato di mx'. L'istanza è simile al seguente:

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 è disponibile nel pacchetto monad-products sotto il nome Product.

+1

La soluzione di ehird significa anche che l'azione f viene eseguita due volte. Questo potrebbe essere inaspettato se le monadi mem 'hanno effetti collaterali osservabili. – Lemming

Problemi correlati