Grundlagen der Programmierung 2 Aufgabenblatt Nr. 5 Aufgabe 1

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