coldwa.st
Alle LeitfädenProgrammierungWebDatenWerkzeugeDatenbankenHaskellKonzepteCabal & BuildsToolchainCompilerPerformanceEditor & HLS

Haskell · Syntax · Listen

List Comprehensions in Haskell, erklärt

Von ColdwastAktualisiert am 14. Juni 20266 Min. Lesezeit#haskell#lists#syntax
Quellcode auf einem Bildschirm
Quellcode auf einem Bildschirm — List Comprehensions sind eine knappe Art, im Code Listen aufzubauen.

Eines der ersten Dinge, die Haskell elegant machen, ist die List Comprehension: eine knappe Art, aus bestehenden Listen eine neue Liste zu bauen, in Anlehnung an die mathematische Mengenschreibweise, an die Sie sich vielleicht aus der Schule erinnern. Dieser Leitfaden erklärt die Syntax, mehrere Generatoren, Guards und den Bezug zwischen Comprehensions und map sowie filter.

Die Grundsyntax

Eine List Comprehension hat die Form [ output | generator, condition ]. Lesen Sie den senkrechten Strich als „sodass“:

-- the squares of 1 to 10
squares = [x*x | x <- [1..10]]
-- [1,4,9,16,25,36,49,64,81,100]

Hier ist x <- [1..10] ein Generator: Er zieht jedes x aus der Liste [1..10], und der Teil vor dem Strich, x*x, ist der Ausgabeausdruck, der auf jedes Element angewendet wird.

Guards hinzufügen (Filtern)

Zeilen Quellcode auf einem dunklen Bildschirm
Codezeilen auf dem Bildschirm — ein Guard behält nur die Elemente, die eine Bedingung erfüllen.

Ein Guard ist eine boolesche Bedingung, die nur die Elemente behält, die sie erfüllen:

-- even numbers from 1 to 20, doubled
result = [x*2 | x <- [1..20], even x]
-- [4,8,12,16,20,24,28,32,36,40]

Sie können mehrere Guards kombinieren, durch Kommas getrennt; alle müssen wahr sein, damit ein Element aufgenommen wird.

Mehrere Generatoren

Mit mehr als einem Generator iteriert die Comprehension über jede Kombination (wie verschachtelte Schleifen), der Reihe nach:

-- all pairs from two small lists
pairs = [(x, y) | x <- [1,2,3], y <- ['a','b']]
-- [(1,'a'),(1,'b'),(2,'a'),(2,'b'),(3,'a'),(3,'b')]

Der am weitesten rechts stehende Generator variiert am schnellsten. Sie können auch einen späteren Generator von einem früheren abhängig machen — etwa indem Sie y aus [x..10] ziehen.

Ihr Bezug zu map und filter

Eine Comprehension ist im Wesentlichen map und filter in einer einzigen lesbaren Form. Diese sind gleichwertig:

[x*2 | x <- xs, even x]
map (*2) (filter even xs)

Nehmen Sie, was sich im jeweiligen Fall am besten liest. Comprehensions glänzen, wenn Sie mehrere Generatoren oder mehrere Guards haben; map/filter lassen sich gut in point-free-Pipelines verketten. Weil Haskell lazy ist, berechnet eine Comprehension über eine unendliche Liste wie [1..] nur die Elemente, die Sie tatsächlich verbrauchen.

FAQ

Was ist ein Generator in einer List Comprehension? Der Teil x <- xs: Er zieht jeden Wert von x aus der Liste xs, um den Ausgabeausdruck zu speisen.

Was ist ein Guard? Eine boolesche Bedingung (wie even x), die nach einem Komma steht; nur die Elemente, für die sie wahr ist, werden behalten.

Kann ich mehrere Generatoren verwenden? Ja — die Comprehension erzeugt jede Kombination, wobei der am weitesten rechts stehende Generator am schnellsten variiert, wie verschachtelte Schleifen.

Sind Comprehensions einfach map und filter? Konzeptionell ja für die einfachen Fälle; Comprehensions sind oft besser lesbar mit mehreren Generatoren oder Guards, während map/filter sich gut in Pipelines verketten lassen.

Zur Sprache hinter der Syntax sehen Sie was Haskell ist; Comprehensions sind eine der Eigenschaften, die es knapp und ausdrucksstark machen.

Unabhängiger, von der Community gepflegter Leitfaden. coldwa.st ist eine Ressourcen-Website rund ums Programmieren; dieser Artikel ist ein neuer, eigenständiger Erklärtext zu List Comprehensions in Haskell, ohne Verbindung zu den Maintainern der Sprache. Der Code spiegelt das Standardverhalten von Haskell/GHC wider — prüfen Sie es anhand der aktuellen GHC-Dokumentation.