Konzepte der Programmierung Programmierkurs 2 Sommer 2017 Universität Konstanz Informatik & Informationswissenschaft M. Grossniklaus, J. Fuchs, L. Wörteler 5. Übungsblatt (Ausgabe: 22. Mai 2017 — Abgabe bis: 29. Mai 2017, 15:00 Uhr) Aufgabe 1 (6 Punkte) Der naive Ansatz, eine rekursive Funktion im λ-Kalkül zu realisieren, scheitert. Betrachten wir die Fakultätsfunktion: ( 1 für n = 0 n! := n · (n − 1)! für n ≥ 1 Eine erste Umsetzung in den λ-Kalkül würde wahrscheinlich zu folgendem Punkt führen: λn. if (= n 0) 1 (× n (f (− n 1))) Da es im λ-Kalkül (wie bisher definiert) nicht möglich ist, einen Teilausdruck so an eine Variable zu binden, dass man ihn in sich selbst referenzieren kann, müsste man für die Metavariable f den gesamten Ausdruck einsetzen, den wir gerade zu definieren versuchen. Dieser enthielte aber wieder ein f, sodass durch wiederholtes Einsetzen ein unendlich großer λ-Ausdruck entstünde. Das ist nicht zulässig. Man kann aber dennoch eine endliche Repräsentation der rekursiv definierten Fakultätsfunktion formulieren. Dazu bedient man sich des sogenannten Y-Kombinators (Kombinatoren sind Ausdrücke im λ-Kalkül ohne freie Variablen) Y = λx. (λy. x (y y)) (λy. x (y y)) und einer modifizierten, nicht-rekursiven Definition der Fakultät, in der wir die Funktion für den rekursiven Aufruf g als zusätzliches Argument erwarten: f = λg. λn. if (= n 0) 1 (× n (g (− n 1))) Nun entspricht Y f der Fakultätsfunktion. Vollziehen Sie dies nach, indem Sie die wohlbekannte Reduktion mit dem Argument 2 durchführen. Vereinfachen Sie also den Ausdruck Yf 2 des λ-Kalküls! Sie können dabei wiederkehrende Teilausdrücke abkürzen. Aufgabe 2 (2 Punkte) Schreiben Sie eine Funktion middle :: [a] -> a die das mittlere Element der übergebenen Liste zurückgibt (bei einer ungeraden Anzahl von Elementen). Hat die Liste 2p Elemente für ein p ∈ N, so soll das p-te Element zurückgegeben werden. Beispiele: middle [1,2,3] _ 2, middle "test" _ ’e’ Aufgabe 3 (2 Punkte) Schreiben Sie eine Funktion, die überprüft ob alle Listenelemente gleich sind: allEqual :: [Integer] -> Bool Beispiele: allEqual [42,42,42,42,42,42,42,42] _ True, allEqual [1,1,1,2,1] _ False 1 Aufgabe 4 (4 Punkte) Schreiben Sie eine Funktion gaps :: Double -> [Double] -> [(Double, Double)] so dass gaps delta xs die Paare aller aufeinander folgenden Zahlen in xs ausgibt, die weiter als delta voneinander entfernt sind. Nehmen Sie dabei an dass delta immer größer oder gleich Null ist. Beispiel: *Main> gaps 2.2 [1.2, 3.4, 12.5, 6.14, 8, 11] [(3.4,12.5),(12.5,6.14),(8.0,11.0)] Aufgabe 5 (5 Punkte) Schreiben Sie eine Funktion insSort :: (a -> a -> Bool) -> [a] -> [a] die ein Vergleichsprädikat lt :: a -> a -> Bool und eine Liste ` als Argument bekommt. Die Ausgabe soll die bezüglich der durch lt definierten Ordnung mit Insertion Sort sortierte Liste ` sein. Dabei funktioniert Insertion Sort wie folgt: Die zu sortierenden Elemente werden der Reihe nach in eine (dann bereits sortierte) Ergebnisliste eingefügt. Schreiben Sie also zunächst eine Hilfsfunktion insert :: (a -> a -> Bool) -> a -> [a] -> [a] die dieses erledigt. Beispiel: Main> insert (<) 3 [1,2,5,7,9] [1,2,3,5,7,9] Main> insSort (>) [7,9,1,2,1,5] [9,7,5,2,1,1] Aufgabe 6 (6 Punkte) f, g, und h Die folgenden neun Ausdrücke zeigen alle Möglichkeiten, drei Variablen • mit Anwendung durch Juxtaposition, • durch den Anwendungsoperator $, oder • mit der Komposition . zu kombinieren. Teilen Sie diese in Gruppen äquivalenter Ausdrücke ein. f g h f g . h f g $ h -- 1 -- 2 -- 3 f . g h f . g . h f . g $ h -- 4 -- 5 -- 6 f $ g h f $ g . h f $ g $ h -- 7 -- 8 -- 9 Tipp: Entfernen Sie zunächst alle Vorkommen von . und $, indem Sie Klammern und ggf. λ-Abstraktionen mit neuen Variablen einführen.