2012-08-10 1 views
4

Quel est le type de classe équivalente à ce qui suit le dictionnaire existentiellement quantifié, inspiré par le type Pipe:classe de type existentiellement quantifié

{-# LANGUAGE ExistentialQuantification, PolymorphicComponents #-} 

data PipeD p = forall cat . PipeD { 
    isoI  :: forall a b m r . Iso (->) (p a b m r) (cat m r a b), 
    categoryI :: forall  m r . (Monad m) => CategoryI (cat m r) , 
    monadI  :: forall a b m . (Monad m) => MonadI (p a b m)  , 
    monadTransI :: forall a b  . MonadTransI (p a b)    } 

L'idée approximative Je vais pour essaie de dire que compte tenu de la (PipeLike p) contrainte, nous pouvons alors déduire (MonadTrans (p a b), Monad (p a b m) et (en utilisant le pseudo-code) (Category "\a b -> p a b m r").

Le CategoryI et MonadI ne sont que les équivalents de ces dictionnaires de type classes que j'utilise pour exprimer l'idée que Category, Monad et MonadTrans sont (un peu) super-classes de ce type PipeLike.

Le type Iso est juste le dictionnaire suivant le stockage d'un isomorphisme:

data Iso (~>) a b = Iso { 
    fw :: a ~> b , 
    bw :: b ~> a } 

Répondre

5

Si tel est une classe de type, la valeur dictionnaire est déterminée uniquement par le type p. En particulier, le type cat est déterminé uniquement par p. Cela peut être exprimé en utilisant un type de données associé . Dans une définition de classe, un type de données associé est écrit comme une définition de données sans un membre de droite. Une fois que vous avez exprimé cat comme type, les autres membres peuvent facilement être changés en classes de type, comme je l'ai montré pour Monad et MonadTrans. Notez que je préfère utiliser des signatures explicites pour des types compliqués.

{-# LANGUAGE TypeFamilies, FlexibleInstances, UndecidableInstances #-} 

class Pipe (p :: * -> * -> (* -> *) -> * -> *) where 
    data Cat p :: (* -> *) -> * -> * -> * -> * 
    isoI  :: forall a b m r. Iso (->) (p a b m r) (Category p m r a b) 
    categoryI :: forall a b m. Monad m => CategoryI (Category p m r) 

instance (Pipe p, Monad m) => Monad (p a b m) 

instance Pipe p => MonadTrans (p a b) 
+0

Je pense que les types de données associés sont probablement la bonne direction, même si je ne voulais pas du tout de dictionnaires. J'espérais quelque chose comme: 'classe (Monad (p a b m), MonadTrans (p a b), Catégorie (Cat p)) => PipeLike p {- classe vide -}'. Le truc d'isomorphisme était simplement lié au type quantifié existentiellement, ce qui n'est pas nécessaire si j'utilise le type de données associé. –

+0

Vous ne pouvez pas créer de superclasses 'Monad' et' MonadTrans', car étant donné 'p', il n'y a aucun moyen de choisir' a', 'b' et' m'. Vous pouvez, cependant, faire des instances comme je l'ai montré. Ils fonctionneront comme les interfaces originales. – Heatsink

+0

Cela a du sens. Merci d'avoir éclairci mes pensées à ce sujet. Je vais accepter ça. –