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?
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
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
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.
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% 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.
Nun, ich denke, in Haskell sind Sie auf Ссылка beschränkt:
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.
Tags und Links haskell list recursion pattern-matching the-little-schemer