Ich möchte eine Typklasse für geometrische Objekte definieren, die zusammen geschnitten werden können:
class Intersect a b c | a b -> c where
intersect :: a -> b -> c
-- Language extensions: -XMultiParamTypeClasses, -XFunctionalDependencies
Die Idee ist, universelle Schnittfunktionen zu haben, die Objekte unterschiedlichen Typs verarbeiten können. Man könnte sich solche Fälle vorstellen wie
instance Intersect Line Plane (Maybe Point) where
...
instance Intersect Plane Plane (Maybe Line) where
...
Ich möchte aber auch erklären, dass die Kreuzung kommutativ ist:
instance (Intersect a b c) => Intersect b a c where
intersect x y = intersect y x
-- Language extensions: -XUndecidableInstances
Das Problem ist, dass jedes Mal, wenn ich auswerte, intersect x y
ohne zuerst eine Instanz des Formulars zu definieren Intersect a b c
, wobei a
es sich um den Typ x
und b
den Typ handelt y
, das Programm in eine Endlosschleife gerät , die vermutlich durch eine rekursive Instanzdeklaration über die Kommutativität verursacht wird. Im Idealfall möchte ich, dass intersect Egg Bacon
die Typprüfung fehlschlägt, weil keine solche Instanz definiert wurde, und mich nicht in einer Endlosschleife einschließt. Wie kann ich das umsetzen?
quelle
Antworten:
Erstens könnten Sie das kommutative Paket verwenden. In diesem Fall würden Sie die Typensignatur
intersect
wie folgt ändern , andernfalls würde der Rest Ihres Codes "nur funktionieren":Sie können QuickCheck jedoch auch mit hspec verwenden, um einen Eigenschaftstest für alle Instanzen Ihrer Typklasse auszuführen, um sicherzustellen, dass diese tatsächlich pendelt. Dies kann den Overhead reduzieren - Sie müssten einen Benchmark durchführen, da ich es nicht genau weiß. Zum Beispiel:
quelle