Programmieren in Haskell Giegerich Programmieren in Haskell Organisation WS 2013/2014 Programmiersprachen Haskell Syntax Robert Giegerich Universität Bielefeld AG Praktische Informatik October 30, 2013 Vordefinierte Datentypen Listen Sprechstunden Programmieren in Haskell Giegerich Organisation GZI-Arbeitsraum (V2-240) Tutoren-Sprechstunden (V2-228) http://www.techfak.uni-bielefeld.de/ags/pi/ lehre/AuDIWS13/#ueb http://www.techfak.uni-bielefeld.de/ags/rbg/ de/gzi-tutoren.html Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Was sind Programmiersprachen? Definition Programmiersprachen regeln die textuelle (oder graphische) Darstellung von Algorithmen, damit sie von einem Computer ausgeführt werden können. Was ist ein Algorithmus? Ein Computer? Was können sie (nicht) leisten? Siehe A&D-Vorlesung! Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Wichtigste Kriterien für Programmiersprachen Wie gut können WIR uns in der Sprache ausdrücken? Wie gut kann der Computer die Programme ausführen? Dabei hat “gut” zwei ganz verschiedene Bedeutungen ... Ebenen der Programmierung Entwicklung von Algorithmen: Abgegrenzte und mathematisch wohldefinierte Aufgabe Verwendung einer Programmiersprache Einzelarbeit oder Kleingruppe Kriterium: Korrektheit und Effizienz alias Programmierung “im Kleinen” Entwicklung von Software: Größere Aufgabe mit diversen Funktionen Markt- und Anwenderbezug, Termine!! Arbeit in großen, auch verteilten Teams Kombination verschiedener Programmiersprachen Kriterium: Software-Lebenszyklus, Erweiterbarkeit alias Programmierung “im Großen” Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Ausbildungskonzept der TechFak Ausgangspunkt: Informatiker müssen im Lauf ihres Berufslebens mit einer Vielzahl von Programmiersprachen und Softwaresystemen arbeiten. Darauf müssen sie vorbereitet werden. Zwei (sehr unterschiedliche) Programiersprachen im ersten Jahr 1. Semester: Funktionale Programmierung (Haskell) 2. Semester: Objektorientierte Programmierung (Java) 3. Semester: Techniken der Projektentwicklung (TdPE) 4. Semester ff: projektspezifische Programmiersprachen (Perl, Python, C und C++, Bellman’s GAP, u.v.a.) Irgendwann: Scala (??) Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Was gehört zu einer Programmiersprache? Anwendungsbereich: Universell oder spezifisch? Eine Sprachdefinition legt fest: Syntax: Wie schreibt man etwas hin? Semantik: Und was bedeutet das dann? Pragmatik: Welche Zeichen und Konventionen werden verwendet? Ein Programmiersystem enthält Compiler, Interpreter Laufzeitsystem Bibliotheken Entwicklungsumgebung Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Wie lernt man eine Programmiersprache Programmieren in Haskell Giegerich Man lernt Organisation Pragmatik: Gewöhnung Programmiersprachen Syntax: Beispiele, Feedback vom Compiler, immer wieder Nachschlagen Haskell Semantik: Lehrbuch/Vorlesung, Übung/Diskussion Ästhetik: Welches ist die “einfachste” Lösung einer Aufgabe? Syntax Vordefinierte Datentypen Listen Semantische Grundkonzepte von Programmiersprachen In den meisten Sprachen findet man Module oder Pakete Programmieren in Haskell Giegerich Namen und Variablen Organisation Regeln der Sichtbarkeit und Gültigkeit Programmiersprachen vordefinierte Operationen, (arithmetische) Ausdrücke Haskell Anweisungen verschiedener Art (Iteration, Fallunterscheidung) Abstraktionsmechanismen: Klassen, Methoden, Funktionen, Prozeduren, Parameter vordefinierte Datentypen und Typ-Definitionen Typ-Prüfung oder Typ-Inferenz Rechenmodell Syntax Vordefinierte Datentypen Listen Haskell Haskell gehört zur Klasse der funktionalen Programmiersprachen seit 1990 vom “Haskell Committee” entwickelt für die Public Domain benannt nach dem Logiker Haskell B. Curry, aufbauend auf den Sprachen ML und Miranda “rein” funktional – alle Berechnungen durch Funktionen beschrieben, d.h. keine “Behälter”, keine Anweisungen, kein vorher/nachher nicht-strikte Auswertung stark typisiert und polymorph; Typinferenz Layout-sensitiv Die wichtigsten Haskell-Implementierungen: Hugs (Interpreter), GHC (Compiler), (GHCI Interpreter) Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Funktionen als Bürger erster Klasse Programmieren in Haskell Funktionen gibt es in allen Programmiersprachen. In einer funktionalen Sprache sind Funktionen “first class citizens”: Funktionen sind den Daten gleichberechtigt. Sie können Giegerich Organisation Programmiersprachen Haskell Argumente von (anderen) Funktionen sein Ergebnisse von (anderen) Funktionen sein anonym oder benannt sein über beliebigen Datentypen definiert werden 1 Funktionen höherer Ordnung ersetzen “Kontrollstruktur” map :: ( a -> b ) -> [ a ] - >[ b ] Syntax Vordefinierte Datentypen Listen Haskell Pragmatik und Syntax Wir schreiben in Haskell Literate Skripts in der Programm-Datei steht ein beliebiger Text; Programmieren in Haskell Giegerich Zeilen, die mit > beginnen, enthalten Programmcode Organisation 1 2 Mein erstes Programm Programmiersprachen Autor : Heinz Heinrichsen ( mit Hilfe von meiner Oma ) Haskell 3 4 > gruss = " Hello world ! " Vordefinierte Datentypen 5 6 7 1 2 Geschafft !!! = = = = = = = == = = = == = = = = = = = = = = Tausend Gruesse Autor : Die Oma vom Heinz 3 4 5 Syntax > ngruesse n = concat ( take n hellos ) > hellos = " Hello World ! " : hellos Listen Namen versus Schlüsselwörter Programmieren in Haskell Giegerich Organisation Namen bezeichnen Werte (aller Art) und sind frei wählbar Schlüsselwörter strukturieren das Programm; sie dürfen nicht als Namen verwendet werden Namen und Schlüsselwörter dürfen nicht durch Leerzeichen oder Zeilenende unterbrochen werden Nicht zu verwechseln: Schlüsselwörter und vordefinierte Namen Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Schlüsselwörter 1 2 3 case class data default deriving do else if import in infix infixl infixr instance let module newtype of then type where _ Programmieren in Haskell Giegerich Organisation Vergleich Programmiersprachen Haskell Sprache #Keywords Haskell Scheme C (C89) Java Ada C++ 21 23 32 50 72 74 Syntax Vordefinierte Datentypen Listen Groß- und Kleinschreibung in Namen Programmieren in Haskell Modulname erster Buchstabe großgeschrieben Modulname == Dateiname Datentypnamen: Großgeschrieben Datentyp-Konstrukturen: Großgeschrieben (z.B. Datentype Bool → Konstruktoren: True und False Variablen, Funktionsnamen: Kleingeschrieben Operatorzeichen → Infix-Schreibweise Sonstige Funktionsnamen: Präfix-Schreibweise Prioritäten und Assoziation definierbar Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Keine (!) Anweisungen Programmieren in Haskell Giegerich keine Statements in Haskell Organisation keine Wertzuweisung, kein FOR, kein WHILE ... → da funktionale Programmiersprache Programmiersprachen Haskell Es wird beschrieben, WAS berechnet werden soll, aber nicht WIE. So wie in (1 + f (2)) ∗ 32 ∗ (4 + g(5)) Hier ist nicht festgelegt, ob zuerst f (2), 32 , oder g(5) berechnet wird Syntax Vordefinierte Datentypen Listen Funktionsdefinitionen 1 2 3 4 Ein Haskell-Programm besteht im wesentlichen aus einer Menge von Definitionen für Funktionen und Datentypen. Einfache Funktionsgleichungen > p x = 5* x ^2 -7* x +9 > aba x y = x ++ y ++ x > f n = if n ==0 then 1 else n * f (n -1) > g x y z = f (x * p y ) - z 5 6 7 8 9 > dnacomp b = if b == > if b == > if b == > if b == Allgemein: ’A ’ ’C ’ ’G ’ ’T ’ then then then then ’T ’ ’G ’ ’C ’ ’A ’ else else else else f p1 ... pk = Ausdruck, der p1 bis pk enthält Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Mustergleichungen (pattern matching) Programmieren in Haskell 1 Mustergleichungen treffen Fallunterscheidungen auf der linken Giegerich Seite (und erlauben mehr als eine Gleichung) > error " illegal symbol in DNAOrganisation " 2 3 4 > ff 0 = 1 > ff n = n * f (n -1) Programmiersprachen -- ueberlappende Muster Haskell Syntax 5 6 7 8 9 10 > > > > > dnaComp dnaComp dnaComp dnaComp dnaComp ’A ’ ’C ’ ’G ’ ’T ’ _ = = = = = Vordefinierte ’T ’ Datentypen Listen ’G ’ ’C ’ ’A ’ error " illegal symbol in DNA " _ bezeichnet ein Argument, das nicht gebraucht wird Fehlerbehandlung Es gibt mehrere Möglichkeiten, Fehler zu behandeln in Haskell Programmen (mindestens 8) einfachster Mechanismus ist die Funktion error error msg darf überall in einem Ausdruck stehen msg ist ein String error msg führt zum Programmabbruch mit Ausgabe von msg Die Funktion hat einen ganz besonderen Typ: error :: String -> a Example 1 2 3 > divide a b = > if b == 0 then error " divide by zero " > else div a b Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Präfix, Infix, Postfix-Notation Die Mathematik hat viele Schreibweisen für Ausdrücke erfunden, um sie gut lesbar zu machen Programmieren in Haskell Giegerich Organisation Programmiersprachen Notation Präfix Infix Postfix Grafix mathematisch −1, f (x , y , z) x < y , n2 , 2x + 5 0 n!, q f √ 3 1− y Rb in Haskell -1, f x y z x<y, nˆ2, 2*x+5 --root 3 (1 - (root 2 y)) integral a b f a f (x ) dx Präfix-Notation ohne Klammern ist der Regelfall in Haskell. Was ist der Unterschied zwischen f a g b und f a (g b) ? Haskell Syntax Vordefinierte Datentypen Listen Operatoren Zweistellige Funktionen mit Infix-Schreibweise nennt man Operatoren. Boolsche Operatoren sind vordefiniert: || oder && und ‘not‘ Vergleichsoperatoren: < <= == /= . . . Arithmetik: + - * / ‘div‘ ‘mod‘ Zeichenreichen: : ++ Operatoren sind reguläre Funktionen in Haskell; nur die Infix-Notation und die gegebenen Prioritäten sind das Besondere. Example Main> let (+) x y = x*y in 2+3 6 Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Prefix/Infix-Konversion Funktionen als Operatoren Operatoren als Funktionen ‘fn‘ konvertiert nach Infix (op) konvertiert nach Prefix Example Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Main> 23 Main> 23 Test> 23 Test> 23 21 + 2 (+) 21 2 div 69 3 69 ‘div‘ 3 Vordefinierte Datentypen Listen Prefix/Infix: Prioritäten Programmieren in Haskell Giegerich Flexible Anwendung von Funktionen Organisation Deklaration von Prioritäten möglich meist geeignet vordefiniert –s. Haskell report Funktionsanwendung in Präfix hat höchste Priorität 1 2 3 f x + g y * 2 ist ( f x ) + (( g y ) *2) fuer einstelliges f und g Achtung bei Definitionen : Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen 4 5 f ( x : xs ) ys = x : f xs ys braucht Klammern !! Bedingter Ausdruck 1 if expr1 then expr2 else expr3 Programmieren in Haskell Giegerich Example 1 f a b Organisation = if a <= b then a +1 else b -2 Programmiersprachen Haskell Kein If-Statement! if expr1 then expr2 ? Fehler! → hier wäre der Wert des Ausdrucks im else-Fall nicht definiert Vergleichbar mit dem Bedingungsoperator in C/Java: cond_expr ? expr2 : expr3 Syntax Vordefinierte Datentypen Listen Sichtbarkeitsbereiche Programmieren in Haskell Giegerich Alle (modernen) Programiersprachen haben Sichtbarkeitsbereiche (scopes). Jeder Name ist in dem Bereich sichtbar in dem er definiert wurde und in allen darin eingebetteteten Bereichen ... ... es sei denn, er wird verschattet Scopes in einem Programm sind also “verschachtelt”. Explizite Regeln gelten für Sichtbarkeit über Modulgrenzen hinweg. Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Layout und Abseitsregel “Whitespace” sind Zeichen ohne Bedeutung: Leerzeichen, NeueZeile, Kommentar Haskell-Programme sind whitespace-sensitive es gilt die Offside-Rule (Abseitsregel) → die Einrückung ist entscheidend 1 2 3 4 > dreh (x , y ) = > schieb (x , y )= > heb (x , y ) = > ( -y , x ) ( x +1 , y ) (x , y +1) Giegerich Organisation Programmiersprachen Haskell in der Regel Verzicht auf Trennzeichen wie ; {}, aber explizite Verwendung von ; {} ist möglich Example (richtig vs falsch) Programmieren in Haskell Syntax Vordefinierte Datentypen Listen > dreh (x , y )= ( -y , x ) > schieb (x , y )=( x +1 , y ) > heb (x , y )= (x , > y +1) Layout definiert Sichtbarkeitsbereiche Programmieren in Haskell Giegerich Neue Bereiche entstehen nach of, where, let: Organisation Example (richtig) 1 2 3 4 5 6 > > > > > > show xs = where show ’ show ’ show ’ Programmiersprachen " [ " ++ show ’ xs ++ " ] " Haskell Syntax Nil = "" ( Cons x Nil ) = show x ( Cons x xs ) = show x ++ " ," ++ show ’ xs Vordefinierte Datentypen Listen Layout Programmieren in Haskell Definitionen gleicher Stufe müssen in der gleichen Einrücktiefe stehen Example (falsch) Giegerich Organisation Programmiersprachen Haskell 1 2 3 4 5 6 > > > > > > show xs = " [ " ++ show ’ xs ++ " ] " where show ’ Nil = "" show ’ ( Cons x Nil ) = show x show ’ ( Cons x xs ) = show x ++ " ," ++ show ’ xs Syntax Vordefinierte Datentypen Listen Explizite Scopes Programmieren in Haskell Giegerich 1 2 3 4 5 Gleichwertig sind Organisation Example Programmiersprachen > f x = g x + > where { g > f x = g x + > where g x h x h x h = = x = x * x ; h x = x + x } x x * x x + x Haskell Syntax Vordefinierte Datentypen Listen Allgemeine Abseitsregel Scopes sind Sichtbarkeitsbereiche von (Gruppen von) Definitionen Programmieren in Haskell Giegerich alle Definitionen eines Scope stehen in der gleichen Einrücktiefe Organisation tieferes Einrücken bedeutet Fortsetzung der aktuellen Definitionszeile Haskell nach let, where, of, do bestimmt der nächste Buchstabe die neue Einrücktiefe Ausrücken nach links beendet den aktuellen Scope Vorteile ?? Nachteile ?? Programmiersprachen Syntax Vordefinierte Datentypen Listen Noch mehr Syntax Programmieren in Haskell Giegerich Organisation Die folgenden Syntax-Elemente werden wir erst spaeter kennelernen, wenn die entsprechenden Sprachkonstrukte behandelt werden. Sie sind hier nur der Vollständigkeit halber aufgeführt. Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Case-Ausdruck (pp.) vielfache Fallunterscheidung statt verschachtelte If-Expressions überall wo ein Ausdruck stehen kann Pattern matching Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell 1 2 3 4 5 case expr of pat1 | guard1 -> expr1 pat2 | guard2 -> expr2 pat3 | guard3 -> expr3 ... Pattern kann leer sein statt pat | True -> gilt auch die Konvention pat -> otherwise als default Syntax Vordefinierte Datentypen Listen Case-Ausdruck Programmieren in Haskell Giegerich Organisation Example 1 2 3 4 5 > laststr xs = case reverse xs of > [] -> " leer " > ( l : ls ) | l == 1 -> " eins " > ( l : ls ) | l == 2 -> " zwei " > otherwise -> " ganz viele " Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Let Expression let decl1 decl2 ... in expr 1 2 3 4 Kann überall dort stehen wo ein Ausdruck stehen kann lokaler Scope (Sichtbarkeitsbereich) 2 3 1 2 3 > func a b > > Giegerich Organisation Programmiersprachen Example 1 Programmieren in Haskell Haskell = let square x = x * x plus a b = a + b in plus ( square a ) ( square b ) Versus: > square x = x * x > plus a b = a + b > func a b = plus ( square a ) ( square b ) Hier sind plus und square auch außerhalb von func bekannt. Syntax Vordefinierte Datentypen Listen Where-Notation lokale Definitionen bei Funktionsdefinitionen case-Ausdrücken Module-Definition . . . Example Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell 1 2 3 > f x = square x + square x > where > square x = x * x vs. let Ausdruck notationelle Betonung syntaktischer Zucker where kann nicht überall stehen Syntax Vordefinierte Datentypen Listen Where-Notation Programmieren in Haskell Giegerich Organisation 1 2 3 4 5 Schachtelungen auch möglich: > foo x = ... f ... > where > f x = ... g ... > where > g x = .... Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Modul-Aufbau Programmieren in Haskell Modulname Imports Definitionen Giegerich Organisation 1 2 > module Meinmodul > where Programmiersprachen Haskell 3 4 Syntax > import Data . List Vordefinierte Datentypen 5 6 > splits n = [ splitAt k [1.. n ] | k < -[1.. n -1]]Listen Main> splits [ ( [1 ( [1,2 ( [1,2,3 ( [1,2,3,4 5 ],[ ],[ ],[ ],[ 2,3,4,5] 3,4,5] 4,5] 5] ) ) ) ) , , , ] Wächter (Guards) in Funktionsdefinitionen (pp.) 1 2 3 4 > fn pat1 pat2 ... > | guard1 = expr1 > | guard2 = expr2 > ... syntaktische Zucker für Funktionsdefinitionen Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell ersetzt geschachtelte if-Anweisungen guards (Wächter) sind Ausdrücke (vom Typ Bool) Example 1 2 3 4 howManyEqual n m p | ( n == m ) && ( m == p ) = 3 | ( n == m ) || ( m == p ) || ( n == p ) = 2 | otherwise = 0 Syntax Vordefinierte Datentypen Listen Pattern matching Pattern Matching auf natürlichen Zahlen Werten Datentyp-Konstruktoren Joker _ 2 3 Giegerich Organisation Programmiersprachen Haskell auf der linken Seite von Funktionsdefinitionen Syntax in case-Ausdrücken Vordefinierte Datentypen Example 1 Programmieren in Haskell > take ’ :: Int -> [ a ] -> [ a ] > take ’ ( n +1) ( a : as ) = a : take ’ n as > take ’ _ _ = [] Listen Pattern matching In der Anwendung wird die erste Gleichung benutzt, deren Muster auf die Argumente passen. 2 3 4 > > > > f f f f ( a : b : c : d : ds ) ( a : as ) ( a :[]) [a] = = = = ... ... ... ... 7 8 Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen 5 6 Giegerich Organisation Example 1 Programmieren in Haskell > g 0 > g 1 > g _ = ... = ... = ... Wo es geht, wählt man die Muster einander ausschließend. Typen in Haskell Haskell verwendet strong typing: Programmieren in Haskell Giegerich Jeder Wert hat einen Typ; Funktionen dürfen nur auf Argumente des richtigen Typs angewandt werden Organisation Typen können vom Compiler geprüft werden Programmiersprachen Typisierung kostet keinen Rechenaufwand zur Laufzeit Haskell Haskell verwendet parametrischen Typ-Polymorphismus Funktionen können allgemeine Typen mit Typ-Parametern haben; z.B. map:: (a -> b) -> [a] -> [b] Bei der Anwendung einer polymorphen Funktion konkretisiert sich ihr Typ Haskell verwendet Typ-Klassen – davon spaeter mehr. Syntax Vordefinierte Datentypen Listen Datentypen Programmieren in Haskell Ein Datentyp ist eine Mengen von Werten, worauf Operationen (Funktionen) definiert werden können. Giegerich Organisation eingebaute Datentypen sind vordefiniert und haben oft eine besondere Notation Programmiersprachen benutzerdefinierte Datentypen werden durch Typdefinitionen eingeführt; haben Standard-Notation Syntax Typdeklarationen geben zu neuen Namen den Typ ihres Werts an Listen Typdeklarationen sind optional. Sie dienen hauptsächlich der Lesbarkeit. Haskell Vordefinierte Datentypen Funktionstypen 1 1 2 3 4 1 2 Der wichtigste Datentyp ist die Funktion, allgemein a -> b Konkrete Funktionen haben speziellere Typen, z.B. > power :: Int -> Int -> Int > isqrt :: Int -> Float > id :: a -> a > id x = x Mehrstellige Funktionen und Funktionen höherer Ordnung ergeben sich, wenn man für a und b selbst wieder Funktionstypen einsetzt > (+):: Int -> Int -> Int > (:):: a -> [ a ] -> [ a ] 3 4 > map :: (a - > b ) -> [ a ] -> [ b ] map ist also eine zweistellige Funktion, deren erstes Argument selbst eine Funktion ist Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Gestaffelte Funktionen Programmieren in Haskell Giegerich 1 1 1 Mehrstelligen Funktionen gibt man den “gestaffelten” Typ a -> b -> c ... -> y -> z -- 25 - stellig was (per Definition von ->) das Gleiche ist wie a -> ( b -> ( c ...( y -> z )...)) aber etwas anderes als (a ,b ,c ,... , y ) -> z Das letzte wäre eine 1-stellige Funktion mit einem 25-Tupel als Argument. Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Eingebaute Datentypen: Zahlen Programmieren in Haskell Elementare eingebaute Datentypen in Haskell sind: Ganze Zahlen (Integer, Int) Funktionen darauf sind z.B.: +, -, *, div, mod, ^ Fließkommazahlen (Float, Double) +, /, ^, sqrt Konstanten können mehreren Typen angehören: Wert mögl. Typen 1, -5, 100, 0.314e1 Int, Integer, Float, Double 2.0, 2e3, 3.14e0 Float, Double 1,-5, 120 Int, Integer Integer sind ganze Zahlen beliebiger Stellenzahl Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Typklasse Listen Num Fractional Integral Eingebaute Datentypen: Bool, Char, String Programmieren in Haskell Giegerich Wahrheitswerte (Bool): True, False &&, ||, not Zeichen (Char): ’a’, ’A’, ’\’ ... Zeichenketten (String), wobei String = [Char] "abraham", "2XG5", "" ... Listen ([a]) [], :, ++, reverse, take, drop Listen sind polymorph und kommen gleich noch ausführlicher! Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Typen von Ausdrücken Programmieren in Haskell Ausdrücke haben Typen: 1 2 3 4 5 6 7 8 9 Giegerich Organisation 42 :: Int 3 + 4 :: Int 4.2 :: Float True :: Bool " Hallo Welt ! " :: String -- bzw . [ Char ] [1 ,2 ,3] :: [ Int ] [] :: [ a ] [[]] :: [[ a ]] Hier sind einige Typen spezieller als es sein muss! Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Typinferenz in Ausdrücken Programmieren in Haskell Giegerich Organisation Hugs> :t (1+2) 1 + 2 :: Num a => a Hugs> :t (4.2) 4.2 :: Fractional a => a Hugs> :t 2/3 2 / 3 :: Fractional a => a Klasse => ... nennt man einen Typkontext Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Typen einschränken Durch explizite Typ-Angaben kann man den allgemeinsten Typ einschränken: Programmieren in Haskell Giegerich Hugs> 2 / 3 0.6666666666666 Organisation Programmiersprachen Hier wird für 1 und 2 ein Typ der Klasse Fractional a abgeleitet. Jetzt die Einschränkung: Hugs> (2::Int) ERROR - Cannot *** Instance *** Expression / (3::Int) infer instance : Fractional Int : 2 / 3 Hugs> (2::Int) ‘div‘ (3::Int) 0 Haskell Syntax Vordefinierte Datentypen Listen Typklassen In Haskell sind Typen in Klassen organisiert. Typen sind dabei Instanzen von Klassen. Beispiele für Typklassen Programmieren in Haskell Giegerich Organisation Eq Überprüfung auf Gleichheit. In der Klasse Eq sind die Operationen == und /= definiert. Instanzen z.B.: Int, Float, Double, String Ord Ordnungsrelation. In der Klasse Ord sind die Operationen <,>,<=,>= definiert. Instanzen z.B.: Int, Float, Double, String Num Umfasst die numerischen Typen, z.B. Int, Float, Double Operationen: +,-,* Show Werte eines Typs der Instanz der Klasse Show ist, lassen sich ausgeben Z.B. Int, Float, Double, String Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Definition von Typklassen Programmieren in Haskell Giegerich Natürlich kann man selbst Typklassen neu definieren Organisation Programmiersprachen Haskell bestehende Typklassen erweitern konkrete Datentypen zu Instanzen von Typklassen machen Das entspricht in etwa den abstrakten Klassen oder Interfaces in Java, die durch konkrete Klassen implementiert werden. Syntax Vordefinierte Datentypen Listen Tupel-Typen Notation ( a1, a2, a3, ... ) vordefinierte Funktionen: fst snd ... Komponenten können verschiedene Typen haben vs. Liste Example 1 2 fst :: (a , b ) -> a fst (x , y ) = x 3 4 5 snd :: (a , b ) -> a snd (_ , y ) = y Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Void Programmieren in Haskell Giegerich Organisation Unit-Datentyp in Haskell: () Programmiersprachen Haskell einziges Element: () Syntax vergleichbar mit void in C/Java Vordefinierte Datentypen Listen Listen in der funktionalen Programmierung Programmieren in Haskell Listen gibt es in allen Programmiersprachen, aber in der funktionalen Programmierung werden sie besonders viel benutzt. Dafür gibt es einen polymorphen Datentyp für Listen aus Elementen von beliebigem, aber gleichem Typ viele vordefinierte Funktionen auf Listen eine spezielle Notation für Listen, Listenbeschreibungen ähnlich der mathematischen Mengen-Notation Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Der polymorphe Listen-Typ [a] Notation: [1,2,3,4] – geschönte Notation 1:2:3:4:[] – Standard-Notation mit Konstruktoren (:) :: a -> [a] -> [a] ”Cons” [] :: [a] ”Nil” [1..10] Typ-Notation: [a], [Int] usw. Main> 1:2:3:4:[] [1,2,3,4] Example 1 2 3 > length ’ :: [ a ] -> Int > length ’ [] = 0 > length ’ ( a : as ) = 1 + length ’ as Programmieren in Haskell Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Listenbeschreibungen Programmieren in Haskell 1 2 3 4 1 2 Listenbeschreibungen sind der mathematischen Giegerich Mengen-Notation nachempfunden. Beispiel: Organisation sm = [ x | x <- " abraham " , x < ’i ’] Programmiersprachen pairs = [( a , b +1) | a <- " aber " , b <- [1 ,2 ,3]] Haskell evenodd = [( a ,b , a + b ) | a <- [1..10] , b <- [11..20] , Syntax even a == odd b ] Vordefinierte Allgemeine Form: Datentypen Listen [ f x y ... | x <- X , cond x , y <- Y , cond x y , ...] X, Y, ...: Listen, aus denen Elemente kommen cond: Bedingungen, die diese erfuellen muessen f x y ...: Elemente der neuen Listen, die aus den ausgewaehlten x, y,... berechnet werden Listenbeschreibungen für Zahlenfolgen Programmieren in Haskell 1 2 3 4 5 6 Besonders komfortable Notation gibt es für Zahlenfolgen: l1 = [1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10] l2 = [1..10] l3 = [1..] l4 = [1 ,5..42] l5 = [1 ,5 ..] l6 = [10 ,8 .. 1] Aufsteigende und absteigende Zahlenfolgen; die Differenz der beiden ersten Zahlen gibt die Schrittweite und Richtung an, .. bedeutet Fortsetzung, bis zum Endwert wenn angegeben, sonst unendlich. Giegerich Organisation Programmiersprachen Haskell Syntax Vordefinierte Datentypen Listen Mehr über Listen Programmieren in Haskell Giegerich Organisation Programmiersprachen Es folgen viele Beispiele von Funktionen über Listen. Siehe Datei listintro.lhs Haskell Syntax Vordefinierte Datentypen Listen