Einführung Einführung Gliederung Programmierparadigmen Einführung in Haskell 1 D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg Einführung Einleitung Sprachelemente Skripte Lexik Prelude Listen Weitere Funktionen c Sommer 2011, 4. April 2011, 2011 D.Rösner D. Rösner PGP 2011 . . . Einführung 1 D. Rösner PGP 2011 . . . Einleitung Sprachelemente Skripte Lexik Prelude Einführung Programmiersprache Haskell: 2 Einleitung Sprachelemente Skripte Lexik Prelude Haskell benannt nach Haskell B. Curry einer der Pioniere des λ-Kalkül erste Spezifikation der Sprache Ende 80er Jahre interaktive Programmierumgebungen, z.B. WinGHCi aktuelle Version: Haskell 98 GHC . . . Glasgow Haskell Compiler frei erhältlicher Interpreter auch für andere gängige Plattformen Download, Tutorials, usw.: http://www.haskell.org/ einige Bücher (Auswahl): [Tho99], [Bir00] [CK02] [Hut06] D. Rösner PGP 2011 . . . 4 D. Rösner PGP 2011 . . . 5 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Haskell Einleitung Sprachelemente Skripte Lexik Prelude funktionale Programme in Haskell Elementarer Einstieg verwende WinGHCi als ’Taschenrechner’ Grundrechenarten: Definitionen von Funktionen und anderen Werten durch Gleichungen Addition: + Subtraktion: Multiplikation: * Division: Definition assoziiert Namen (Identifikator) mit Wert eines bestimmten Typs Syntax: ganzzahlig: ‘div‘ Gleitkomma: / <name> :: <type> <name> = <expression> Exponentiation: ^ Beachte: es gelten die üblichen Vorrangregeln (Präzedenzregeln) ansonsten: Verwenden von Klammern D. Rösner PGP 2011 . . . Einführung 6 Einleitung Sprachelemente Skripte Lexik Prelude D. Rösner PGP 2011 . . . Einführung funktionale Programme in Haskell cont. Einleitung Sprachelemente Skripte Lexik Prelude Haskell – Sprachelemente lies ‘::’ als ‘hat Typ’ oder ‘ist vom Typ’ Beispiele: Typisierung: jedes Objekt in Haskell hat einen wohldefinierten Typ size :: Int size = 12 + 13 Zweck der Typisierung: frühzeitiges Erkennen von Programmierfehlern (type checking) schon vor Programmausführung (statische Analyse) square :: Int -> Int square n = n * n D. Rösner PGP 2011 . . . 7 8 D. Rösner PGP 2011 . . . 10 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Haskell – Sprachelemente Einleitung Sprachelemente Skripte Lexik Prelude Zur Unterscheidung zwischen Int und Integer vordefinierte elementare Typen (auch Sorten genannt) für Konstante (= nullstellige Funktionen): Zur Klasse Int gehören ganze Zahlen, die sich mit einer festen Zahl von Bytes darstellen lassen. Bool Int Char Float Integer Rational Double der Wert der Variablen maxBound::Int gibt die grösste als Int darstellbare ganze Zahl an. Dieser Wert ist (bei WinGHCi) 2147483647. Will man beliebig grosse ganze Zahlen verarbeiten, so sollte man den Typ Integer verwenden. Vorschau: durch Deklaration mit type lassen sich benutzerdefinierte Typen einführen D. Rösner PGP 2011 . . . Einführung D. Rösner PGP 2011 . . . 11 Einleitung Sprachelemente Skripte Lexik Prelude Einführung Typisierung cont. 12 Einleitung Sprachelemente Skripte Lexik Prelude Typisierung cont. Typ von Funktionen (auch Funktionalität genannt) : Definitions- und Wertebereich durch -> getrennt angegeben Interpretation einer Typdeklaration wie scale :: Picture -> Int -> Picture erstens: scale hat zwei Argumente: Beispiel: double :: Int -> Int double n = 2*n das erste ist vom (nutzerdefinierten) Typ Picture, das zweite vom (vordefinierten) Typ Int bei mehreren Argumenten werden deren Typen durch -> verbunden zweitens: das Ergebnis der Anwendung von scale ist vom Typ Picture Beispiel: max mit 2 Argumenten aus Int und Wert aus Int max :: Int -> Int -> Int D. Rösner PGP 2011 . . . 13 D. Rösner PGP 2011 . . . 14 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung vordefinierte arithmetische Operatoren Einleitung Sprachelemente Skripte Lexik Prelude vordefinierte arithmetische Operatoren cont. + . . . Summe zweier Zahlen div . . . ganzzahlige Division * . . . Produkt zweier Zahlen ˆ . . . Exponentiation: 2 ˆ 3 gibt 8 - ... mod . . . Rest bei ganzzahliger Division (modulo) abs . . . Absolutbetrag Differenz, wenn infix verwendet; umgekehrtes Vorzeichen bei Präfixverwendung (vgl. negate) D. Rösner PGP 2011 . . . Einführung negate . . . ändere Vorzeichen D. Rösner PGP 2011 . . . 15 Einleitung Sprachelemente Skripte Lexik Prelude Einführung vordefinierte Vergleichsoperatoren Einleitung Sprachelemente Skripte Lexik Prelude einige vordefinierte Operatoren bzw. Konstanten für Float für ganze Zahlen, d.h. Typ Int -> Int -> Bool: >, >=, ==, / =, <=, < Name(n) + - * / ˆ ** exp log logBase pi signum sqrt cos, sin, tan acos, asin, atan ceiling, floor, round fromInt diese Vergleichsoperatoren sind – wie auch die arithmetischen Operatoren – ‘überladen’ und auch auf Float anwendbar Typ dann: Float -> Float -> Bool für == gilt auch Bool -> Bool -> Bool bzw. sogar allgemein t -> t -> Bool , sofern für den Typ t Gleichheit definiert (Hinweis: t hier sog. Typvariable) D. Rösner PGP 2011 . . . 16 17 Typ Float -> Float -> Float Float -> Int -> Float Float -> Float -> Float Float -> Float Float -> Float Float -> Float -> Float Float Float -> Float Float -> Float Float -> Float Float -> Float Float -> Int Int -> Float D. Rösner PGP 2011 . . . Bem. xn xy ex ln x loga x π Rundung Konversion 18 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Operatoren Einleitung Sprachelemente Skripte Lexik Prelude Operatoren werden infix verwendet, d.h. 3 + 4 Exponentiation ˆ als rechts-assoziativer Operator aber: Verwendung eines Operatorsymbols <op> in Präfixposition möglich mit Notation (<op>) , d.h. (+) 3 4 == 3 + 4 *Main> 2 ^3 ^ 3 134217728 *Main> 2 ^(3 ^ 3) 134217728 *Main> (2 ^ 3) ^ 3 512 können assoziativ sein; z.B. +, * nicht-assoziative Operatoren werden festgelegt als links-assoziativ oder rechts-assoziativ z.B. - links-assoziativ, d.h. a - b - c == (a - b) - c D. Rösner PGP 2011 . . . Einführung 19 Einleitung Sprachelemente Skripte Lexik Prelude D. Rösner PGP 2011 . . . Einführung Operatoren 20 Einleitung Sprachelemente Skripte Lexik Prelude Operatoren und Funktionen Funktionsanwendung hat höchste Bindungsstärke allgemeine Schreibweise: Funktionsname vor Argument(e) f v1 v2 ...vn Operatoren haben Bindungsstärke oder Fixität (engl. fixity) z.B. Beachte: da Funktionsanwendung höhere Bindung als jeder andere Operator, wird f n+1 interpretiert als (f n)+1 * hat Fixität 7, + hat 6, ˆ hat 8, daher a + b * c == a + (b * c) und a ˆ b * c == (a ˆ b) * c D. Rösner PGP 2011 . . . für andere Interpretation ist explizite Klammerung notwendig: f (n+1) 21 D. Rösner PGP 2011 . . . 22 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Konversionen von Operatoren und Funktionen zwei Arten von Dateistilen: werden Infix-Operatoren in Klammern eingeschlossen, so können sie als Funktionen vor ihren Argumenten verwendet werden Skripte (Extension ‘.hs’): alles ist Programmtext, sofern nicht explizit als Kommentar gekennzeichnet Beispiel: (+) :: Int -> Int -> Int Beispiel:Verwendung: (+) a b == a + b Kommentare bis Zeilenende eingeleitet durch zwei aufeinanderfolgende ‘-’ Abschnittskommentare zwischen ‘{-’ und ‘-}’ umgekehrt: Funktionen können zu Operatoren gemacht werden durch Einschluss des Funktionsnamen in sog. Backquotes a ‘max‘ b == max a b D. Rösner PGP 2011 . . . Einführung Einleitung Sprachelemente Skripte Lexik Prelude D. Rösner PGP 2011 . . . 23 Einleitung Sprachelemente Skripte Lexik Prelude Einführung zwei Arten von Dateistilen: cont 25 Einleitung Sprachelemente Skripte Lexik Prelude Beispiel eines Skripts {... mehrere Zeilen Kommentartext ... -} -- Berechnung der Fakultät mit Konditional if literate Skripte (Extension ‘.lhs’): alles ist Kommentar, sofern nicht am Zeilenanfang durch ‘>’ als Programmzeile gekennzeichnet literat . . . ‘wörtlich’ fak :: Int -> Int fak n = if n == 0 then 1 else n * fak (n - 1) D. Rösner PGP 2011 . . . 26 D. Rösner PGP 2011 . . . 27 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Beispiel eines literaten Skripts Einleitung Sprachelemente Skripte Lexik Prelude Haskell – lexikalische Konventionen Die Berechnung der Funktion Fakultät ist ein Standardbeispiel fuer Rekursion. Identifikatoren: Bezeichner von Variablen, von Typen von Funktionen usw. > fak :: Int -> Int > fak n = if n == 0 then 1 else n * fak (n - 1) Identifikatoren müssen in Haskell mit einem Buchstaben beginnen Eine Variante mit Pattern-Matching: dieser kann von einer beliebigen Sequenz von Buchstaben, Ziffern, Unterstrichen (_) und einzelnen Anführungszeichen (’) gefolgt sein > fak 0 = 1 > fak n = n * fak (n - 1) D. Rösner PGP 2011 . . . Einführung 28 Einleitung Sprachelemente Skripte Lexik Prelude Einführung Haskell – lexikalische Konventionen 30 Einleitung Sprachelemente Skripte Lexik Prelude Haskell – lexikalische Konventionen Konventionen für führende Großbuchstaben bzw. Kleinbuchstaben kleine Sammlung sog. reservierter Wörter können nicht als Identifikatoren benutzt werden dazu zählen: case|class|data|default|deriving|do|else |if|import|in|infix|infixl|infixr|instance |let|module|newtype|of|then|type|where|_ alle Namen, die in Definitionen von Werten verwendet werden (d.h. also auch alle Funktionsnamen), müssen mit einem kleinen Buchstaben beginnen, ebenso die Bezeichner für Variable und Typvariable mit einem Großbuchstaben beginnen Typnamen (z.B. Int), Konstruktoren, True und False, Modulnamen und auch die Namen von Typklassen D. Rösner PGP 2011 . . . D. Rösner PGP 2011 . . . 31 D. Rösner PGP 2011 . . . 32 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Haskell – lexikalische Konventionen Einleitung Sprachelemente Skripte Lexik Prelude Funktionen in Prelude.hs Empfehlung: mnemonische, ’sprechende’ Namen verwenden z.B. Prelude.hs enthält viele nützliche Funktionen zinssatz statt nur z /usr/local/hugs98-Dec2001/share/hugs/lib/Prelude.hs Empfehlung: bei Namen, die aus mehreren Worten zusammengesetzt sind, den Beginn des zweiten Worts (und ggf. folgender Wörter) in Großbuchstaben schreiben z.B. letztesElement D. Rösner PGP 2011 . . . Einführung D. Rösner PGP 2011 . . . 33 Einleitung Sprachelemente Skripte Lexik Prelude Einführung Listenfunktionen im Prelude: head head (x:_) :: [a] -> a = x last last [x] last (_:xs) :: [a] -> a = x = last xs tail tail (_:xs) :: [a] -> [a] = xs init init [x] init (x:xs) :: [a] -> [a] = [] = x : init xs D. Rösner PGP 2011 . . . 35 Einleitung Sprachelemente Skripte Lexik Prelude Listenfunktionen cont. 36 null null [] null (_:_) :: [a] -> Bool = True = False (++) [] ++ ys (x:xs) ++ ys :: [a] -> [a] -> [a] = ys = x : (xs ++ ys) map map f xs :: (a -> b) -> [a] -> [b] = [ f x | x <- xs ] filter filter p xs :: (a -> Bool) -> [a] -> [a] = [ x | x <- xs, p x ] D. Rösner PGP 2011 . . . 37 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Listenfunktionen cont. Funktionen in Prelude.hs concat concat :: [[a]] -> [a] = foldr (++) [] length length :: [a] -> Int = foldl’ (\n _ -> n + 1) 0 (!!) (x:_) (_:xs) (_:_) [] Funktionen, die ein Paar als Argument nehmen, vs. Funktionen mit zwei Argumenten :: [a] -> Int -> a 0 = x n | n>0 = xs !! (n-1) _ = error "Prelude.!!: negative index" _ = error "Prelude.!!: index too large" !! !! !! !! D. Rösner PGP 2011 . . . Einführung x curry curry f x y :: ((a,b) -> c) -> (a -> b -> c) = f (x,y) uncurry uncurry f p :: (a -> b -> c) -> ((a,b) -> c) = f (fst p) (snd p) D. Rösner PGP 2011 . . . 38 Einleitung Sprachelemente Skripte Lexik Prelude Einführung Funktionen in Prelude.hs cont. id id Einleitung Sprachelemente Skripte Lexik Prelude Einleitung Sprachelemente Skripte Lexik Prelude Funktionen in Prelude.hs: Faltung :: a -> a = x foldl :: (a -> b -> a) -> a -> [b] -> a foldl f z [] = z foldl f z (x:xs) = foldl f (f z x) xs const const k _ :: a -> b -> a = k (.) (f . g) x :: (b -> c) -> (a -> b) -> (a -> c) = f (g x) foldr :: (a -> b -> b) -> b -> [a] -> b foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) flip flip f x y :: (a -> b -> c) -> b -> a -> c = f y x ... D. Rösner PGP 2011 . . . 39 40 D. Rösner PGP 2011 . . . 41 Einführung Einleitung Sprachelemente Skripte Lexik Prelude Einführung Funktionen in Prelude.hs Literatur: I Richard Bird. Introduction to functional programming using Haskell. Prentice Hall Europe, 2000. ISBN 0-13-484346-0; 2nd edition. Fehlererzeugung: primitive error :: String -> a Manual M. Chakravarty and Gabriele C. Keller. An Introduction to Computing with Haskell. Pearson Education Australia, 2002. ISBN 1 74009 404 2; also available in German translation. Beispiel einer Kontrollstruktur: until :: (a -> Bool) -> (a -> a) -> a -> a until p f x = if p x then x else until p f (f x) D. Rösner PGP 2011 . . . Einführung Einleitung Sprachelemente Skripte Lexik Prelude Graham Hutton. Programming in Haskell. Cambridge University Press, 2006. ISBN 0521692695. 42 Einleitung Sprachelemente Skripte Lexik Prelude Literatur: II Simon Thompson. Haskell - The Craft of Functional Programming. Addison Wesley Longman Ltd., Essex, 1999. 2nd edition, ISBN 0-201-34275-8; Accompanying Web site: http://www.cs.ukc.ac.uk/people/staff/sjt/craft2e. D. Rösner PGP 2011 . . . 44 D. Rösner PGP 2011 . . . 43