Prof. Dr. Manfred Schmidt-Schauß Künstliche Intelligenz/Softwaretechnologie Fachbereich Informatik und Mathematik/ Institut für Informatik Goethe-Universität Frankfurt am Main Grundlagen der Programmierung 2 Sommersemester 2016 Aufgabenblatt Nr. 5 Abgabe: Mittwoch 18. Mai 2016 vor! der Vorlesung Aufgabe 1 (35 Punkte) Arithmetische Ausdrücke mit den vier Grundrechenarten können in Haskell durch den folgenden rekursiven Datentyp Baum in Kombination mit dem Datentyp Op dargestellt werden: data Op = Add | Sub | Mult | Div deriving(Eq,Show) data Baum a b = Blatt a | Knoten (Baum a b) b (Baum a b) deriving(Eq,Show) Dabei ist die Division gleichbedeutend zu div in Haskell, also einer Division, die für ganzzahlige Parameter ein ganzzahliges Ergebnis liefert. Der arithmetische Ausdruck (((20+30)-2)·(33/3)) entspricht dem folgenden Baum vom Typ Baum Integer Op: Mult Div Sub 2 Add 20 33 3 30 a) Stellen Sie den oben gezeigten Baum unter Verwendung von Baum und Op dar. (5 Punkte) b) Implementieren Sie eine Funktion toString :: Baum Integer Op -> String, die zu einem Baum den dazugehörigen arithmetischen Ausdruck als String liefert. Für den obigen Baum soll "(((20+30)-2)*(33 ‘div‘ 3))" berechnet werden. (8 Punkte) c) Implementieren Sie eine Funktion eval :: Baum Integer Op -> Integer, die einen Baum zu einem Ergebnis auswertet, das dem Ergebnis des durch den Baum dargestellten arithmetischen Ausdrucks entspricht. (7 Punkte) d) Implementieren Sie eine Funktion modify :: Baum Integer Op -> Baum Integer Op, die in einem Baum Additionen durch Subtraktionen und umgekehrt sowie Multiplikationen durch Divisionen und umgekehrt ersetzt. Außerdem sollen alle Zahlen jeweils mit -1 multipliziert werden. Für den obigen Baum soll daher der folgende Baum berechnet werden: (7 Punkte) Div Add Sub Mult -2 -33 -20 -30 1 -3 e) Implementieren Sie eine Funktion simplify :: Baum Integer Op -> Baum Integer Op, die für einen arithmetischen Ausdruck k und eine Zahl l in einem Baum k − (−l) zu k + l und k + (−l) zu k − l vereinfacht. (8 Punkte) Aufgabe 2 (15 Punkte) Geben Sie für jeden der folgenden Typen eine Funktion in Haskell an, deren allgemeinster Typ genau der genannte Typ ist. a) b) c) d) (3 (4 (4 (4 Char -> [Bool] [a] -> [b] -> [c] -> (a, [b], [a]) ([a], a -> a -> a -> b) -> b (a -> b) -> c -> (c -> a) -> b Punkte) Punkte) Punkte) Punkte) Gehen Sie dabei folgendermaßen vor: Definieren Sie in einer Quelltextdatei die Funktionen aufgabeA, aufgabeB, aufgabeC und aufgabeD ohne deren Typ anzugeben. Laden Sie anschließend die Datei in den ghci und lassen Sie sich den Typ der Funktionen berechnen: Dafür geben Sie (für Aufgabe a)) :type aufgabeA im Interpreter ein. Wenn der angezeigte Typ dem Typ der Aufgabenstellung (bis auf Umbenennung der Typvariablen) entspricht, haben Sie die Aufgabe gelöst. Sei z.B. die gesuchte Funktion vom Typ a -> (Bool,Bool), so kann man definieren: beispiel x = (False,True) Der ghci liefert dann als Typ: :type beispiel beispiel :: t -> (Bool, Bool) Daher hat beispiel den gesuchten Typ (Umbenennung der Typvariablen t durch a ist erlaubt). Aufgabe 3 (50 Punkte) Berechnen (Rechenweg erforderlich!) Sie jeweils den (polymorphen) Typ der Ausdrücke a) map fst b) foldr1 seq c) (.) (foldr1 seq) (map fst) (15 Punkte) (15 Punkte) (20 Punkte) mithilfe der in der Vorlesung vorgestellten Typregeln. Sie können dabei die Typen für map, fst, foldr1, seq und (.) sowie bereits berechnete Typen verwenden, ohne diese (erneut) herzuleiten. Die Typen sind: map (.) foldr1 fst seq :: :: :: :: :: (a -> b) -> [a] -> [b] (c -> d) -> (e -> c) -> e -> d (f -> f -> f) -> [f] -> f (g, h) -> g i -> j -> j Beachten Sie, dass Sie bei Verwendung der Anwendungsregel auch die Typsubstitution mithilfe von Unifikation berechnen müssen. Geben Sie hierzu ebenfalls den Rechenweg an. 2