2012-06-25 4 views
6

Ich bin eine einfache Hash-Baumstruktur in dem folgende Programm schreiben hash_lookup.hs:Haskell: Schwierigkeit den Kontextes Einbetten (Eq a) in eine Datendeklaration

module Main where 

    data (Eq a) => HashTable a b = HashChildren (a, [HashTable a b]) | Hash (a, b) deriving (Show) 

    getKey :: HashTable a b -> a 

    getKey (HashChildren (k, hs)) = k 
    getKey (Hash (k, h)) = k 

    lookUp :: [a] -> HashTable a b -> Maybe (HashTable a b) 

    lookUp [] table = return table 
    lookUp _ (Hash _) = Nothing 
    lookUp (p:path) (HashChildren (_, ts)) = lookUp path (head (dropWhile (\x -> (getKey x) /= p) ts)) 

getKey beabsichtigt ist, den Stammschlüssel eines gegebenen Hashtable Abrufen , und lookUp nimmt eine Liste von Strings und soll dem ersten gefundenen Pfad folgen, bis es entweder den vollständigen Pfad erreicht oder ausfällt (ich bin mir bewusst, dass dies kein natürliches Verhalten für einen Baum ist, aber das ist was mein Tutorial will).

Ich habe zwei Fragen: 1) Warum erhalte ich eine Fehlermeldung, mir zu sagen, dass a /= a (aus der letzten Zeile) ist nicht zulässig, da es No instance for (Eq a) ist (die Fehlermeldung im Terminal), trotz (Eq a) in der Datenerklärung ?

2) Andere als die Fehler Ich erhalte und das scheinbar seltsame Verhalten der Lookup-Funktion, dann ist dies gut oder idiomatische Haskell?

Dank

+1

Die Datentyp-Kontext-Funktion wird in der zukünftigen Version von Haskell entfernt http://www.haskell.org/pipermail/haskell/2011-Januar/022497.html – sdcvvc

Antwort

8

Einer der häufigsten „Fallstricke“ in Haskell ist, dass, wenn Sie setzen Klasse Zwänge auf einer data Erklärung, jeder Funktion, die den Typ verwendet, muss auch die Klassenbeschränkungen haben. Aus diesem Grund ist Ihre data Deklaration in Haskell nicht idiomatisch und Sie sollten ihre Klassenbeschränkung beseitigen. Sie erhalten nichts, um die Klassenbeschränkung in der Deklaration data trotzdem zu deklarieren.

Grundsätzlich müssen die Funktionstypen die Klassenbeschränkung wiederholen. Wie sonst kann ein Benutzer der Funktion wissen, dass er eine Instanz der fraglichen Klassen verwenden muss? Beachten Sie, dass Sie eine Funktion f definiert in Bezug auf eine Funktion g definiert in Bezug auf eine h definieren können, die in Bezug auf Ihre HashTable a b Art definiert ist, so dass f Ihren HashTable Typ überhaupt nicht erwähnt, aber wegen der Typabhängigkeiten es nimmt ein Argument vom Typ a, das indirekt und letztlich als erster Parameter Ihres HashTable Typs verwendet wird. f 's Typ muss haben die Klasseneinschränkung, Haskell richtig so schließt, und es wird Ihre Typ Anmerkungen zurückweisen, wenn sie es fehlt.

+0

Vielen Dank - das macht ausgezeichneten Sinn! – GabrielG

+1

Beachten Sie, dass der neueste Sprachstandard direkt Kontexte von Datentypen entfernt hat. –

Verwandte Themen