Das ist eine Signatur Die Signatur der Funktionen f => f :: Int -> Int -> Int Wenn nicht explizit angegeben dann ist der Typkonstruktor rechtsassoziativ geklammert (man hat sich darauf geeinigt da man in der Praxis häufiger rechtsassoziative Typkonstruktoren verwendet als Linksassoziative ) d.h: f :: Int -> Int -> Int entspricht => f :: (Int -> (Int -> Int)) anonyme Funktion : (\n -> (add 2) n) length :: [a] -> Int a in der Typsignatur von length heißt Typvariable. Typvariablen werden gewöhnlich mit Kleinbuchstaben vom Anfang des Alphabets bezeichnet: a, b, c ,… Typdefinition: Z.b.: Tree a = definierende Typvariable angewandte Nil | Typvariable Leaf a Node a (Tree a) (Tree a) Wichtige Signaturen: (man sollte auch wissen was diese Funktionen machen und wie man sie verwendet) filter :: (a -> Bool) -> [a] -> [a] map :: (a -> b) -> [a] -> [b] foldl :: (a -> b -> a) -> a -> [b] -> a add :: Int -> (Int -> Int) add m n = m+n add’ :: (Int,Int) -> Int add’ (m,n) = m+n Sprechweise: Die Funktion... • add ist curryfiziert • add’ ist uncurryfiziert curry :: ((a,b) -> c) -> (a -> b -> c) curry f x y = f (x,y) uncurry :: (a -> b -> c) -> ((a,b) -> c) uncurry g (x,y) = g x y • Curryfizieren ersetzt Produkt-/Tupelbildung “×” durch Funktionspfeil “->”. • Decurryfizieren ersetzt Funktionspfeil “ ->!” durch Produkt- /Tupelbildung “×”. • (Parametrische) Polymorphie ... gleicher Code trotz unterschiedlicher Typen • ad-hoc Polymorphie (synonym: Überladen (engl. Overloading))... unterschiedlicher Code trotz gleichen Namens (mit sinnvollerweise i.a. ähnlicher Funktionalität) Rekursionen: Generell: eine Rechenvorschrift heißt rekursiv, wenn sie in ihrem Rumpf (direkt oder indirekt) aufgerufen wird. Schlichte (repetitive) z.b.: ggt (größter gemeinsamer Teiler) lineare z.b.: fac (Fakultätsfunktion) geschachtelte z.b.: fun91 (Funktion aus der Vorlesung) baumartige kaskadenartige z.b.: fib (Fibonacci -Zahlen) Indirekte oder auch verschränkte (wechselweise) zwei oder mehr Funktionen rufen sich wechselweise auf z.b.: even u. odd Algebraische Typen: Summentypen (Verkehrsmittel) o Aufzählungstypen (Jahreszeiten, Boolesche Werte) ein oder mehrere Konstruktoren, alle nullstellig o Produkttypen (Person) nur ein Konstruktor, mehrstellig Rekursive Typen Polymorphe Typen Nullstellige Konstruktoren führen zu Aufzählungstypen. (Alternativenlose) mehrstellige Konstruktoren führen auf Produkttypen. Mehrere (null- oder mehrstellige) Konstruktoren führen auf Summentypen. newtype-Deklarationen sind auf Typen mit nur einem Konstruktor eingeschränkt. Ist bei der Implementierung so Effizienz wie Type , und bei der Übersetzung so Typsicherheit wie Data. Unbedingt zu beachten ist – type führt neue Namen für bereits existierende Typen ein (Typsynonyme!), keine neuen Typen. Durch type-Deklarationen eingeführte Typsyonyme • tragen zur Dokumentation bei und • erleichtern (i.a.) das Programmverständnis aber...• führen nicht zu (zusätzlicher) Typsicherheit! Eine Typklasse ist eine Kollektion von Typen, auf denen eine in der Typklasse festgelegte Menge von Funktionen definiert ist. (zB.: Eq, Ord , Num) class Size a where -- Definition der Typklasse Size size :: a -> Int instance Size (Tree a) where -- Instanzbildung fuer (Tree a) size Nil = 0 size (Node n l r) = 1 + size l + size r Tree a ist eine Instanz der (gehört zur) Typklasse Size, wenn a zu dieser Klasse gehört. Intuitiv ersetzt die Angabe der deriving-Klausel (automatische Erstellung) die Angabe einer instance-Klausel (manuelle Erstellung). Funktionen, unter deren Argumenten oder Resultaten Funktionen sind, heißen Funktionen höherer Ordnung oder kurz Funktionale. Mithin... Funktionale sind spezielle Funktionen! Des Pudels Kern ...bei Funktionalen ist die => Wiederverwendung! Monaden (sind Konstruktorklassen) erlauben die Reihenfolge, in der Operationen ausgeführt werden, explizit festzulegen. Konstruktorklassen haben Typkonstruktoren als Elemente.Typkonstruktoren sind Funktionen, die aus gegebenen Typen neue Typen erzeugen (Bsp:Tupelkonstruktor ( ), Listenkonstruktor[ ] Auswertungsstrategien: applicative order (leftmost-innermost) normal order (leftmost-outermost) Von Normal Order zu Lazy Evaluation (call-by-need) über Graphentransformation -> Ziel: Vermeidung von Mehrfachauswertungen zur Effizienzsteigerung, garantiert, dass Argumente höchstens einmal (möglicherweise also gar nicht) ausgewertet werden. Lambda Kalkül (Alonzo Church (1936)) Reiner Angewandter (syntaktisch angereichert, praxisnäher)) ist ein spezielles formales Berechnungsmodell, wie viele andere auch Der Lambda Kalkül ist ausgezeichnet durch nur wenige syntaktische Konstrukte, einfache Semantik und der Lambda Kalkül ist Turing-mächtig, da alle “intuitiv berechenbaren” Funktionen im -Kalkül ausdrückbar sind. Die Menge Exp der Ausdrücke des (reinen) l-Kalküls, kurz Lambda Ausdruck ist definiert durch: Name, Abstraktion, Applikation Lambda Konversionen: Alpha Konversion (Umbenennung formaler Parameter) Beta Konversion (Funktionsanwendung) Eta Konversion (Elimination redundanter Funktion) Theorem1:wenn eine Normalform existiert, dann ist sie eindeutig (bis auf Alpha Konversion)! Theorem2:normal order Reduktion terminiert am häufigsten! Ein -Ausdruck ist in Normalform, wenn er durch -Reduktion und -Reduktion nicht weiter reduzierbar ist.