Prüfe, ob die Liste in Haskell flach ist

7

In Der kleine Scheher gibt es eine Funktion, die überprüft, ob die Liste ist flach:

%Vor%

Ich versuche, dieselbe rekursive Funktion in Haskell zu schreiben, habe aber keinen Erfolg:

%Vor%

Wie überprüfe ich, dass der Parameter nicht in der Form [[a]] ? Mit anderen Worten, [1,2,3] ist eine gültige Eingabe, aber [[1,3], [2,4]] und [[[1,2,3]]] sind nicht.

Ich möchte das weiter in rekursiven Funktionen verwenden, die Listen akzeptieren, um sicherzustellen, dass ich nur mit flachen Listen arbeite.

BEARBEITEN: Ich sehe, dass Leute wegen der is_lat :: [a] -> Bool -Typ-Signatur verwirrt sind. Ich stimme jetzt zu, dass ich den Typ zur Laufzeit nicht überprüfen sollte. Ist es jedoch möglich, den Typ zur Kompilierzeit zu überprüfen? Wie kann ich die Funktion nur für flache Listen arbeiten lassen? Oder sollte ich meine Denkweise komplett ändern?

    
Mirzhan Irkegulov 16.04.2013, 14:25
quelle

4 Antworten

19

Sie können sich geschachtelte Listen in Haskell nicht so genau vorstellen wie in Scheme, da sie nicht dieselbe Datenstruktur haben. Eine Haskell-Liste ist homogen, wo eine Lisp- "Liste" tatsächlich näher an einem Rosenbaum liegt (wie von C.A.McCann unten dargelegt). Betrachten Sie als anschauliches Beispiel, wie der WYAS48-Parsing-Abschnitt LispVal definiert.

Wenn Sie wirklich, wirklich , wirklich eine Laufzeitprüfung durchführen möchten, obwohl dies normalerweise eine schlechte Idee und in Haskell sehr unkonventionell ist, schauen Sie in Data.Typeable . Diese Antwort könnte ebenfalls hilfreich sein.

Die wirkliche Antwort auf diese Frage lautet: "Sie müssen in Haskell anders über Ihre Argumente nachdenken als in Lisp, was dazu führt, dass Sie diese Überprüfung niemals selbst zur Laufzeit durchführen müssen" (und ich sage das als Common Lisper, also ich verstehe, wie frustrierend das anfängt).

Addendum : Als Reaktion auf Ihre Bearbeitung sorgt das Typensystem von Haskell automatisch dafür. Wenn Sie beispielsweise eine Funktion vom Typ foo :: [Int] -> Int haben und diese ["One", "Two", "Three"] oder [[1, 2, 3]] übergeben, erhalten Sie einen Kompilierungsfehler, der Ihnen sagt, was gerade explodiert ist und warum. Wenn Sie eine Funktion spezialisieren möchten, geben Sie einfach einen spezifischeren Typ an.

Zum Beispiel (schreiben Sie keinen Code wie diesen, es dient nur zur Veranschaulichung), sagen Sie, Sie haben eine einfache Funktion wie

%Vor%

Wenn Sie dies in GHCi laden und :t myLookup ausführen, wird Ihnen sagen, dass der Typ der Funktionen myLookup :: Eq a => a -> [(a, b)] -> Maybe b ist, was bedeutet, dass ein Schlüssel eines beliebigen Typs verwendet werden kann, der Eq ableitet (alles, was Sie ausführen können) == on). Nun, sagen Sie, dass Sie aus irgendeinem Grund sicherstellen wollen, dass Sie nur Zahlen als Schlüssel verwenden. Sie würden dies sicherstellen, indem Sie eine spezifischere Typdeklaration hinzufügen

%Vor%

Nun, obwohl es im Rumpf der Funktion nichts gibt, was den Umgang mit anderen Schlüsseltypen verhindert, erhalten Sie beim Kompilieren einen Typfehler, wenn Sie versuchen, etwas anderes als Int index oder etwas zu übergeben anders als eine [(Int, a)] map. Als Folge davon

%Vor%

wird kompiliert und läuft gut, aber das

%Vor%

wird auch nicht tun. Auf meinem Rechner passiert es beim Kompilieren mit

%Vor%

Ich hoffe wirklich, dass dich das nicht weiter verwirrt hat.

    
Inaimathi 16.04.2013, 15:20
quelle
13

Dies ist sowohl unmöglich als auch unnötig mit Standard-Haskell-Listen, weil Haskell stark typisiert ist; entweder sind alle Elemente einer Liste selbst Listen (in diesem Fall ist der Typ [a] = [[b]] für einige b ), oder sie sind nicht.

z. Wenn Sie versuchen, eine gemischte Liste zu erstellen, erhalten Sie einen Fehler vom Compiler:

%Vor%     
Fred Foo 16.04.2013 14:31
quelle
11

Der Funktionstyp [a] -> Bool bedeutet implizit forall a. [a] -> Bool , dh er ist für Listen aller möglichen Elementtypen identisch definiert. Das beinhaltet Typen wie [[Int]] oder [[[String]]] oder jede denkbare Verschachtelungstiefe. Aber es ist nicht - und kann nicht - für Ihre Funktion wichtig, was der Elementtyp ist.

Was diese Funktion betrifft, ist die Eingabe immer eine Liste, deren Elemente ein undurchsichtiger, unbekannter Typ sind. Es wird niemals geschachtelte Listen mit demselben undurchsichtigen Typ erhalten.

    
C. A. McCann 16.04.2013 14:57
quelle
0

Nun, ich denke, in Haskell sind Sie auf Ссылка beschränkt:

%Vor%

In nicht strikt typisierten Sprachen hat jedes Objekt Informationen zum Laufzeittyp und kann daher polymorph sein. Dies könnte ein kompliziertes Netzwerk von Zwängen sein, wie in Scala (weniger kompliziert wenn du in C ++ bist), oder einfach "alles ist ein Objekt und Objekt ist alles" wie in rein dynamischen Sprachen (Lisp, JS, ...) .
Haskell ist streng typisiert.

    
bipll 05.09.2013 07:31
quelle