2016-10-21 2 views
2

Considérons un type d'utilisateur avec deux paramètres, a et b. De toute évidence, ce qui permet à l'utilisateur d'être composé de deux types différents:Utilisation de foncteurs/applicatifs sur des types de données personnalisés avec plusieurs classes de types?

data Users a b = User a b deriving (Show, Eq, Ord) 

Comment pouvons-nous déclarer foncteurs qu'applicatif pour cette instance?

J'ai essayé ces approches ne compilera pas:

instance Functor Users where 
    fmap f(User a b) = User (f a) (f b) 

instance Applicative Users where 
    pure a b = User a b 
    (<*>) User a b = (fmap a) (fmap b) 

Quelle est la raison pour laquelle ils ne seront pas compiler?

+1

Il y a une sorte désadaptation, une instance Functor doit avoir 'genre * -> *' 'votre alors le type user' est de type' * -> * -> * '. Ce que vous voulez est un [Profunctor] (http://hackage.haskell.org/package/profunctors-5.2/docs/Data-Profunctor.html#t:Profunctor). – baxbaxwalanuksiwe

+3

En plus de l'erreur kind, votre implémentation 'pure' ne fonctionnera pas car il n'y a pas de variable' b' dans la définition. Comment voulez-vous pouvoir écrire la fonction 'a -> User a b'? – Lee

+2

@baxbaxwalanuksiwe Voulez-vous dire 'Bifunctor'? – ThreeFx

Répondre

5

Jetez un oeil à Data.Bifunctor pour une classe de type pour ADT qui sont fonctorial dans les deux arguments. User est alors juste un nom fantaisie pour tuple, et cela supporte déjà une telle instance. Déduire une instance de bifonctor est possible dans Haskell. @Bakuriu suggère de définir User comme newtype et d'utiliser l'extension GeneralizedNewtypeDeriving. Pour le second, voir Biapplicative. Comme prévu, son instance pour (,) est:

instance Biapplicative (,) where 
    pure = (,) 
    ap (f, g) (a, b) = (f a, g b) 
+1

Vous pouvez probablement dériver l'instance de la paire en utilisant 'newtype' pour' User' et utiliser l'extension 'GeneralizedNewtypeDeriving'. – Bakuriu