Je veux définir une classe de type pour les objets géométriques qui peuvent être intersectés ensemble:
class Intersect a b c | a b -> c where
intersect :: a -> b -> c
-- Language extensions: -XMultiParamTypeClasses, -XFunctionalDependencies
L'idée est d'avoir une fonction d'intersection à usage général qui peut gérer des objets de différents types. On pourrait imaginer des exemples tels que
instance Intersect Line Plane (Maybe Point) where
...
instance Intersect Plane Plane (Maybe Line) where
...
Mais je veux aussi déclarer que l'intersection est commutative:
instance (Intersect a b c) => Intersect b a c where
intersect x y = intersect y x
-- Language extensions: -XUndecidableInstances
Le problème est que chaque fois que j'évalue intersect x y
sans d'abord définir une instance de la forme Intersect a b c
, où a
est le type de x
et b
est le type de y
, le programme entre dans une boucle infinie , probablement causée par une déclaration d'instance récursive sur la commutativité. Idéalement, je veux que quelque chose comme intersect Egg Bacon
ne parvienne pas à la vérification de type car aucune instance de ce type n'a été définie, pas me piéger dans une boucle infinie. Comment puis-je implémenter cela?
la source
Réponses:
Tout d'abord, vous pouvez utiliser le package commutatif , auquel cas vous modifierez la signature de type de
intersect
ce qui suit, mais sinon le reste de votre code "fonctionnera" simplement:Cependant, vous pouvez également utiliser QuickCheck avec hspec afin d'exécuter un test de propriété sur toutes les instances de votre classe de type pour vous assurer qu'il fait effectivement la navette. Cela peut réduire les frais généraux - vous devriez faire un point de repère car je ne sais pas du haut de ma tête. Par exemple:
la source