2. Elm
2.7 Tupel
Sie haben bis jetzt vier Datentypen kennengelernt: Int
, Float
,
String
und Bool
. Dass statt Int
und Float
manchmal
der "Obertyp" number
verwendet wird, sollten Sie weitestgehend ignorieren.
Im letzten Abschnitt haben Sie aber gesehen, dass es zu diesen primitiven Datentypen auch
zusammengesetzte geben kann, nämlich Paare.
("hello", String.length "hello")
("hello", 5) : (String, Int)
Hier ist also ein neuer Datentyp: (String, Int)
. Mithilfe von Paaren
können wir also aus den vier uns bislang bekannten Typen Int, Float, Bool, String
16 verschiedene Kombinationen herstellen. Generell gilt:
x
ein Ausdruck vom Typ A
ist und y
ein Ausdruck vom Typ
B
,
dann ist
(x,y)
ein Ausdruck vom Typ (A, B)
.
Aber..., Paaare, also Tupel, sind doch selbst wieder Typen. Kann ich das obige Prinzip also
mit x = ("hello", String.length "hello")
und y = "English"
anwenden
und einen
Ausdruck der Form
(("hello", String.length "hello"), "English")
bilden, und hat dieser Ausdruck dann
den Typ
((String, Int), String)
? Probieren wir es aus!
(("hello", String.length "hello"), "English")
(("hello",5),"English") : ( ( String, Int ), String )
Wunderbar! Wir können also Paare verschachteln und erhalten so eine im Prinzip unendliche Menge möglicher Typen! Und da war doch noch etwas: Funktionen sind doch selbst Ausdrücke, und ihr Typ ist ihre Signatur, oder?
f : Int -> Int
f x = n^2
<function> : Int -> Int
(f, "Quadratfunktion")
(<function>,"Quadratfunktion") : ( Int -> Int, String )
In Elm sind Funktionen vollberechtigte Staatsbürgerinnen; sie haben somit auch einen Typ und dürfen Teil eines Tupels sein.
Im Kapitel über die Fibonacci-Zahlen haben wir bereits gesehen, wie nützlich Tupel sein können.
Noch offensichtlicher wird es, wenn wir geometrische Probleme programmieren. Denn
Punkte und Vektoren im zweidimensionalen Raum sind ja "von Haus aus" Objekte
vom Typ (Float, Float)
.
Tupel verarbeiten
Ein neues Tupel zu erschaffen geht ganz einfach:
pair = (4.0, 7.0)
(4, 7): (Float, Float)
Auf die erste und zweite Komponente können Sie mittels Tuple.first
und
Tuple.second
zugreifen:
pair = (4.0, 7.0)
(4, 7): (Float, Float)
Tuple.first pair
4 : Float
Tuple.second pair
7 : Float
Übungsaufgabe 2.7.1 Ich definiere nun ein verschachteltest Tupel:
nestedPair = ("hello", ( (3.0, "my"), "dear"))
Dies ist ein Paar, dessen erste Komponente ein String und dessen zweite Komponente wiederum ein Paar ist etc.
Zeigen Sie, wie Sie mittels Tuple.first
und Tuple.second
auf
die Einzelbestandteile wie 3.0
oder "dear"
zugreifen können!
Geometrische Probleme
Als erstes will ich mit Ihnen eine Funktion schreiben, die einen Vektor
Bezeichnen wir diese Funktion, also Rotation nach links um einen Winkel von
Die zweite Beobachtung ist, dass wir, um
Wir müssen also nur herausfinden, wie
Übungsaufgabe 2.7.2 Schreiben Sie eine Funktion
rotate : Float -> (Float, Float) -> (Float, Float)
rotate angle vector =
...
die einen gegebenen Punkt um den gegebenen Winkel rotiert. Achten Sie darauf, dass die
Funktionen
cos
und sin
Bogenmaß und nicht Grad verwendet; statt 90 Grad
müssen Sie also
Wenn wir zwei Punkte
Wie finden wir nun heraus, ob ein weiterer Punkt
ihr inneres Produkt. Ist es positiv, so ist der Winkel zwischen
Wir verschieben das Bild, so dass
Dann rotieren wir den Vektor
Nun können wir mithilfe des inneren Produktes
leftRightOrOn
, die als Argument eine gerichtete Gerade - Legen Sie zuerst die Signatur der Funktion fest. Mit welchem Datentyp repräsentieren Sie die Gerade?
- Schreiben Sie eine Funktion
innerProduct
, die berechnet. - Schreiben Sie eine Funktion
vectorFromTo p q
, die berechnet. - Schreiben Sie jetzt
leftRightOrOn
insideTriangle p q r v
, die überprüft, ob