Я хочу определить класс типов для геометрических объектов, которые могут пересекаться вместе:
class Intersect a b c | a b -> c where
intersect :: a -> b -> c
-- Language extensions: -XMultiParamTypeClasses, -XFunctionalDependencies
Идея состоит в том, чтобы иметь функции пересечения общего назначения, которые могут обрабатывать объекты разных типов. Можно представить такие случаи, как
instance Intersect Line Plane (Maybe Point) where
...
instance Intersect Plane Plane (Maybe Line) where
...
Но я также хочу объявить, что пересечение коммутативно:
instance (Intersect a b c) => Intersect b a c where
intersect x y = intersect y x
-- Language extensions: -XUndecidableInstances
Проблема в том, что всякий раз, когда я оцениваю intersect x y
без предварительного определения экземпляра формы Intersect a b c
, где a
тип x
и b
тип y
, программа входит в бесконечный цикл , предположительно вызванный рекурсивным объявлением экземпляра о коммутативности. В идеале я хочу, чтобы что-то вроде intersect Egg Bacon
неудачной проверки типов, потому что ни один такой экземпляр не был определен, не заманивает меня в бесконечный цикл. Как я могу это реализовать?
источник
Ответы:
Во-первых, вы можете использовать коммутативный пакет, и в этом случае вы измените сигнатуру типа
intersect
на следующую, но в противном случае остальная часть вашего кода будет «просто работать»:Тем не менее, вы также можете использовать QuickCheck с hspec для запуска теста свойств во всех экземплярах вашего класса типов, чтобы убедиться, что он действительно коммутирует. Это может снизить накладные расходы - вам нужно будет сделать тест, так как я не знаю, по макушке. Например:
источник