Donc Data.Map a dataCast2
défini, ce qui est logique, car il a un constructeur de type arité 2. Par défaut dataCast1
const Nothing
. dataCast2
est facilement défini comme gcast2
.Data.Data - produisant dataCast1 pour un constructeur de type arity 2 (partiellement spécialisé)
Pour référence:
class Typeable a => Data a where
dataCast1 :: Typeable1 t => (forall d. Data d => c (t d)) -> Maybe (c a)
dataCast2 :: Typeable2 t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a)
...
gcast1 :: (Typeable1 t, Typeable1 t') => c (t a) -> Maybe (c (t' a))
gcast2 :: (Typeable2 t, Typeable2 t') => c (t a b) -> Maybe (c (t' a b))
La question posée est la suivante: tout donné dans Data.Data
, Data.Typeable
, etc., et donné un constructeur de type arité 2 pour lequel dataCast2
est défini (par exemple, Map
ou (,)
), est-il possible d'écrire une version de dataCast1
qui fait la bonne chose pour une spécialisation partielle de ce type constructeur, soit pour un constructeur spécifique à la fois, ou en général? Intuitivement, je pense qu'il devrait y avoir une bonne solution, mais mes premiers essais ont planté et brûlé.
Cela ressemble à un problème intéressant, mais je pense que je vais avoir besoin d'un peu plus de fond. D'abord, une question. Que voulez-vous dire par «fait la bonne chose pour une application partielle de ce type de constructeur»? Les constructeurs de type peuvent apparaître partiellement appliqués dans la tête d'une déclaration de classe ou d'instance, cependant, partout ailleurs, ils doivent apparaître complètement appliqués AFAIK. –
@Sean Bon point. Je l'ai changé pour lire "spécialisation partielle". Le point étant de pouvoir appeler 'myDataCast1' avec un résultat de' Maybe (c (Int, a)) 'de la même façon qu'on peut appeler' dataCast1' avec le résultat de 'Maybe (c (Maybe a))'. – sclv