Il y a beaucoup de façons de le faire, sur le plan conceptuel. Malheureusement, la plupart d'entre eux ne fonctionnent pas réellement. Hélas!
Tout d'abord, en tant que programmeur fonctionnel, je parierais que c'est ce que vous vraiment voulez écrire:
instance Listable (\a -> (a, a)) where
asList (p, q) = [p,q]
Malheureusement lambdas niveau de type n'existent pas. Nous pourrions écrire une version nommée du lambda ci-dessus en utilisant un synonyme de type:
type Same2 f a = f a a
instance Listable (Same2 (,)) where { ... }
Ce n'est pas permis non plus, parce que le synonyme de type n'est pas entièrement appliquée. On pourrait plutôt imaginer la classe de type prenant un argument supplémentaire qui décrit comment appliquer les variables de type:
class Listable app f where
asList :: app f a -> [a]
instance Listable __ Maybe where { ... }
instance Listable __ (,) where { ... }
Sans même penser à ce que app
peut-être, cela ne fonctionne pas parce que nous n'avons pas une sorte cohérente pour le paramètre f
. En passant à des choses qui fonctionnent réellement, je pense que la manière la plus courante est d'envelopper l'approche de type synonyme dans un newtype
, puis de traiter simplement de l'emballage et du déballage que cela implique.
newtype Same2 f a = Same2 (f a a)
instance Listable (Same2 (,)) where { ... }
C'est faisable, même si c'est un peu moche. Vous pouvez également définir la composition du constructeur de type et d'autres jouets de cette façon, puis devenir fou avec des expressions sans point de niveau de type enfouies sous un tas de passe-partout.
En approche finale, vous pouvez également encoder l'approche de type lambda ci-dessus « en sens inverse », allant de la version entièrement appliquée, - le paramètre de type simple:
class Listable t where
type ListableElem t :: *
asList :: t -> [ListableElem t]
être capable de faire ce genre de chose est l'une des principales motivations pour les familles de type. La même chose peut être exprimée avec MPTCs et fundeps, mais c'est 1) équivalent et 2) beaucoup plus laid, donc je ne vais pas prendre la peine de l'écrire.
Désolé d'être paresseux pour l'essayer, mais la dernière approche permettrait 'instance Listable (a, a)' - n'est-ce pas? – yatima2975
@ yatima2975: Au lieu d'avoir différentes instances avec '(,)' comme constructeur de type externe, oui. Probablement aurait dû mettre cela comme un exemple dans ma réponse, maintenant que vous le mentionnez ... –