Uso delle classi di tipi Haskell per applicare la commutatività

9

Voglio definire una classe di tipi per oggetti geometrici che possono essere intersecati insieme:

class Intersect a b c | a b -> c where
  intersect :: a -> b -> c
-- Language extensions: -XMultiParamTypeClasses, -XFunctionalDependencies

L'idea è di avere funzioni di intersezione generiche in grado di gestire oggetti di diverso tipo. Si potrebbero immaginare casi come

instance Intersect Line Plane (Maybe Point) where
  ...
instance Intersect Plane Plane (Maybe Line) where
  ...

Ma voglio anche dichiarare che l'intersezione è commutativa:

instance (Intersect a b c) => Intersect b a c where
  intersect x y = intersect y x
-- Language extensions: -XUndecidableInstances

Il problema è che ogni volta che valuto intersect x y senza prima definire un'istanza della forma Intersect a b c , dove a è il tipo di x e b è il tipo di y , il programma entra in un ciclo infinito , presumibilmente causato dalla dichiarazione di istanza ricorsiva sulla commutatività. Idealmente voglio qualcosa come intersect Egg Bacon per fallire nel controllo del tipo perché non è stata definita alcuna istanza, non mi ha intrappolato in un ciclo infinito. Come posso implementarlo?

    
posta Herng Yi 25.01.2015 - 02:34
fonte

1 risposta

1

Per prima cosa, puoi utilizzare il pacchetto commutativo , nel qual caso dovresti modificare la firma del tipo di intersect al seguente , ma altrimenti il resto del tuo codice "funzionerebbe":

instersect :: Commutative a b -> c

Tuttavia, puoi anche usare QuickCheck con hspec per eseguire un test di proprietà su tutte le istanze della tua classe di tipografia per assicurarti che faccia effettivamente il pendolarismo. Ciò potrebbe ridurre le spese generali: dovresti fare un punto di riferimento poiché non lo so in cima alla mia testa. Ad esempio:

import Test.Hspec

main :: IO ()
main = hspec $ do
    describe "intersect" $ do
        parallel $ it "should commute" $ do
            property $ \x y -> intersect x y == intersect (y :: Point) (x :: Line)
    
risposta data 17.06.2017 - 21:57
fonte

Leggi altre domande sui tag