2015-04-29 5 views
7

Sembra che le classi di tipo quali Applicative, Monad e Arrow hanno una sorta di tipo somma equivalente in classi di tipo quali Alternative, MonadPlus e ArrowPlus rispettivamente. Ad esempio, applicativo e alternativa possono essere utilizzati per definire la seguente:prodotto e Somma tipo di Parallels in Haskell Tipo Classi

(<&&>) :: Applicative f => f a -> f b -> f (a, b) 
a <&&> b = (,) <$> a <*> b 

(<||>) :: Alternative f => f a -> f b -> f (Either a b) 
a <||> b = (Left <$> a) <|> (Right <$> b) 

Tuttavia, in tutti questi casi (così come con ArrowChoice), la classe tipo di prodotto è un prerequisito per la classe tipo somma. Esistono regole di classe del tipo o funzioni comuni che dipendono dalla classe dei prerequisiti? Il Typeclassopedia tocca queste relazioni, ma sfortunatamente non sono riuscito a trovare alcun motivo esplicito per la dipendenza.

+0

È possibile che sia impossibile essere una Somma senza essere un Prodotto, ma è possibile solo una Somma. – AJFarmar

+0

@AJFarmar: cosa? – leftaroundabout

risposta

5

Arrow è fondamentalmente la classe per monoidal categories – con “ monoid ” non si riferisce ai Monoid, ma il prodotto -monoid dei tipi Haskell. I.e., con elemento unitario () e moltiplicazione (,). Ora, i tipi di somma costituiscono anche un monoid, ed è quello che usa ArrowChoice. Queste due classi sono in tal senso complementari; ArrowChoice non dovrebbe essere una sottoclasse di Arrow.

In una categoria monoidale, è possibile continuare con monoidal functors. Il modo in cui vengono fuori dipende da quello che usi come tipo monoide. Per (), (,), si ottiene

class ProdMonoidalFtor f where 
    prodUnit ::() -> f() 
    prodZip :: (f a, f b) -> f (a,b) 

type (+) = Either 
class SumMonoidalFtor f where 
    sumUnit :: Void -> f Void 
    sumZip :: f a + f b -> f (a+b) 

scopre il secondo è sostanzialmente inutile, perché è la Voidinitial object di Hask, cioè esiste esattamente un Void -> a (cioè absurd) per tutti i tipia. Tuttavia, ciò che rende certo senso è functors comonoidal con +:

class SumCoMonoidalFtor f where 
    sumCounit :: f Void -> Void -- I bet you find this useless too, but it's not totally. 
    sumCozip :: f (a+b) -> f a + f b 

Ciò a sua volta non avrebbe senso per tipi di prodotti, perché () è la terminale oggetto.

La cosa interessante è che ora ProdMonoidalFtor è equivalente a Applicative:

instance (ProdMonoidalFtor f) => Applicative f where 
    pure x = fmap (const x) $ prodUnit() 
    fs <*> xs = fmap (\(f,x) -> f x) $ prodZip (fs,xs) 

Ci si potrebbe allora sospettare che Alternative è equivalente a SumMonoidalFtor, ma non lo è! In realtà, è equivalente a decisive functors, che sono a comonads come applicativi alle monadi.

Mentre Alternative e MonadPlus non sembrano davvero avere molto supporto matematico, sono essenzialmente quello che si ottiene quando “ non-Kleisliing ” il ArrowChoice classe, ma utilizzando la categoria Kleisli che nasce dalla ProdMonoidalFtor. È tutto un po 'dubbioso.


Ecco considerando solo first/left, second/right, e ***/+++. Per quanto riguarda i restanti &&&, ||| e arr, questi sono più specifici e l'IMO appartiene allo in seperate classes.

+0

'sumZip' è anche inutile dato che puoi avere sia (fmap Left) (fmap Right)', giusto? – chi

+0

@chi: Suppongo di sì, ma non sono sicuro della prova. – leftaroundabout