Funktionale Programmierung mit Haskell/ Funktionen auf Tupel
Funktionen auf Tupel
BearbeitenTupel sind eine andere Form der Datenspeicherung. Sie unterscheiden sich in mehreren Punkten von Listen:
- Tupel werden mit runden Klammern dargestellt, etwa (3,4)
- Tupel besitzen eine feste Zahl von Elementen, d.h. man kann einen Tupel nicht von (3,4) auf (3,4,5) erweitern. Tupel mit einem einzigen Element sind nicht erlaubt, ein 1-Tupel könnte man mit einem Ausdruck verwechseln. Leere Tupel sind erlaubt.
- Elemente eines Tupels sind immer vom selben Typ, d.h. ein Tupel ("September", 1) kann nicht auf (9,1) geändert werden.
Mit diesen Eigenschaften haben Tupel völlig andere Einsatzgebiete als Listen. Sie werden z.B. gerne als Key/Value-Paare verwendet, wenn (wie im unten stehenden Beispiel) zu jedem Land genau eine Vorwahl hinterlegt werden soll.
Mathematische Hintergründe zum Tupel werden auch in der Wikipedia erklärt.
Hier ein paar Anwendungsbeispiele:
Prelude> let ff = (8,9) -- Zuweisung eines Tupels
Prelude> ff -- kann man sich so anzeigen lassen
(8,9)
Prelude> fst ff -- Erstes Element des Tupels (geht nur für 2-Tupel)
8
Prelude> snd ff -- Zweites Element des Tupels (geht nur für 2-Tupel)
9
Prelude> let n = () -- das leere Tupel
Prelude> n
()
Prelude> map fst [(1, 2), (3, 4), (5, 6)] -- Eine Liste von 2-Tupeln, aus der wir die ersten Elemente herausholen
[1,3,5]
Prelude> let x = [(1, 2), (3, 4, 5), (6, 7)] -- Liefert einen Fehler, denn ein 2-Tupel ist kein 3-Tupel
Prelude>
Ein Beispielprogramm mit Key-Value-Tupeln
BearbeitenDa sich Tupel gut für Key-Value-Datenspeicherung eignen, wird diese Technik im folgenden Programm näher erläutert. Dabei werden Zugriffe auf eine Ländervorwahl-Liste dargestellt. Der Key ist dabei das Land, der Value ist die Vorwahl. In dem Beispiel findet der Zugriff auf die Tupel mittels der lookup
-Funktion statt, außerdem wird auch das Haskell-spezifische Maybe
-Konstrukt verwendet.
module KeyValue
where
import Data.Maybe (fromJust, isNothing)
type Land = String
type Vorwahl = Integer
type VorwahlListe = [(Land, Vorwahl)]
laenderListe :: VorwahlListe
laenderListe = [("Afghanistan", 93),
("Ägypten",20),
("Albanien", 355),
("Algerien", 213)] -- usw...
main = do
putStrLn "Bitte ein Land eingeben"
datString <- getLine
let land = datString
let vorw = lookup land laenderListe
if isNothing vorw
then putStrLn ("Das Land "++land++" ist nicht hinterlegt")
else putStrLn ("die Vorwahl von "++land++" ist +"++ show (fromJust vorw))
Erläuterung:
Mit Land
, Vorwahl
und VorwahlListe
werden drei benutzerdefinierte Typen angelegt. Die Funktion lookup
holt mit dem Land
-Schlüssel die Vorwahl aus der laenderListe
.
lookup
liefert einen Maybe
-Typ zurück, das bedeutet: Falls ein Wert zurückgeliefert wird, wird ihm ein Just
vorangestellt. Es muss mit fromJust
oder durch Pattern-Matching vom eigentlichen Rückgabewert extrahiert werden. Wenn kein Wert zurückgeliefert wird (z.B. bei einer unsinnigen Abfrage wie "Egypten") muss dieser Fall speziell abgefangen werden. Dies geschieht in der if
-Anweisung.
Zur Laufzeit sieht das so aus:
$> ghci KeyValue.hs
...
Ok, modules loaded: KeyValue.
*KeyValue> main
Bitte ein Land eingeben
Ägypten
die Vorwahl von Ägypten ist +20
*KeyValue> main
Bitte ein Land eingeben
Egypten
Das Land Egypten ist nicht hinterlegt
*KeyValue>
Benutzerdefinierte Typen mit Tupeln
BearbeitenTupel eignen sich auch dazu, Benutzerdefinierte Typen anzulegen. Beispielsweise kann man ein Datum mit Jahr, Monat und Tag definieren:
Prelude> type Day = (Integer, Int, Int) -- Definition eines Tags als Jahr, Monat und Tag
Prelude> let datum = (2014,12,3) :: Day -- Zuweisung eines Datums
Prelude> datum -- lassen wir es uns anzeigen
(2014,12,3)
Prelude>