Chaque constructeur de type et de type a un type. Quelque chose de simple comme Int
a genre *
. Votre constructeur de type à un seul argument Users
a le type * -> *
; il prend un type et renvoie un nouveau. Votre premier exemple de Users
a le type * -> * -> * -> *
; il faut trois types et renvoie un nouveau.
Functor
fonctionne uniquement avec les constructeurs de type de type * -> *
. Cela vous permet de définir une instance Functor
pour votre deuxième constructeur de type Users
, mais pas votre premier. Réfléchissez à votre premier essai: le constructeur de données Users
prend trois arguments, mais votre définition de fmap
tente de l'appeler avec un seul, la valeur de retour de f. Vous pourriez faire Users
un foncteur aussi longtemps que vous êtes prêt à faire tous les trois champs du même type:
data Users a = Users a a a
instance Functor Users where
fmap f (Users a b c) = Users (f a) (f b) (f c)
En théorie, vous pouvez définir une classe Trifunctor
(il y a une disposition classe Bifunctor
):
class Trifunctor f where
trimap :: (a1 -> b1) -> (a2 -> b2) -> (a3 -> b3) -> f a1 a2 a3 -> f b1 b2 b3
data Users a b c = Users a b c
instance Trifunctor Users where
trimap f g h (Users a b c) = Users (f a) (g b) (h c)
mais il est discutable à quel point ce serait utile. Functor
est utile pour les conteneurs à usage général, car ils ont un large éventail d'utilisations. Users
, d'autre part, semble assez spécifique. Vous n'avez généralement pas besoin de la flexibilité avec laquelle vous le définissez; data User = User Int Int Int
semble fonctionner correctement, et il n'est pas nécessaire de mapper une fonction par-dessus: à quelle fréquence avez-vous besoin de la même fonction pour modifier la hauteur, le poids et l'âge de la même manière?
Le deuxième exemple ne fait pas ce que vous pensez - vous avez besoin d'une indentation sur 'fmap' pour le faire partie de l'instance. Le premier exemple vous avez omis l'erreur qui vous indique le problème (n.b. C'est un problème de genres, les instances de foncteurs sont de type '* -> *'). –
'Pourtant, cela ne compilera pas?' Quelle est l'erreur du compilateur? –