Eu quero definir uma classe de tipo para objetos geométricos que podem ser cruzados:
class Intersect a b c | a b -> c where
intersect :: a -> b -> c
-- Language extensions: -XMultiParamTypeClasses, -XFunctionalDependencies
A idéia é ter funções de interseção de uso geral que possam manipular objetos de tipos diferentes. Pode-se imaginar casos como
instance Intersect Line Plane (Maybe Point) where
...
instance Intersect Plane Plane (Maybe Line) where
...
Mas também quero declarar que a interseção é comutativa:
instance (Intersect a b c) => Intersect b a c where
intersect x y = intersect y x
-- Language extensions: -XUndecidableInstances
O problema é que sempre que eu avalio intersect x y
sem definir primeiro uma instância do formulário Intersect a b c
, onde a
é o tipo x
e b
o tipo de y
, o programa entra em um loop infinito , provavelmente causado por uma declaração de instância recursiva sobre a comutatividade. Idealmente, quero que algo pareça intersect Egg Bacon
falhar na verificação de tipo porque nenhuma instância foi definida, não me prenda em um loop infinito. Como posso implementar isso?
haskell
type-systems
typeclass
Herng Yi
fonte
fonte
Respostas:
Primeiro, você pode usar o pacote comutativo ; nesse caso, você modificaria a assinatura de tipo
intersect
para o seguinte, mas, caso contrário, o restante do seu código "funcionaria":No entanto, você também pode usar o QuickCheck com hspec para executar um teste de propriedade em todas as instâncias da sua classe de tipo para garantir que ele efetivamente seja comutado. Isso pode reduzir a sobrecarga - você teria que fazer uma referência, pois eu não sei de nada. Por exemplo:
fonte