Fachrichtung 6.2 — Informatik Universität des Saarlandes Tutorenteam der Vorlesung Programmierung 1 Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Blatt 2 (Höherstufige Prozeduren, Typinferenz) Hinweis: Dieses Übungsblatt enthält von den Tutoren für das Wiederholungstutorium erstellte Aufgaben. Die Aufgaben und die damit abgedeckten Themenbereiche sind für die Klausur weder relevant noch irrelevant. Typen, Bindungen und Bezeichner Aufgabe 2.1 (Typschema 1 ) Bestimmen Sie die Typschemata folgender Prozeduren: (a) fun p x y = if x then y else 2.0 (b) fun q x = #1((), x=3) (c) fun r f a b = f(a,b) (d) fun s n f x = if n < 100 then x else f(x) (e) fun t f x y = if x < 1 then f(x,y) else f(y,x) Aufgabe 2.2 (Typinferenz) Schreiben Sie Prozeduren mit folgenden Typschemata, ohne dabei explizite Typangaben zu verwenden: (a) (bool * int) → int (b) int → bool → int → unit (c) ∀αβ. int → α → (α → β) → α (d) ∀αβ. ’α → (’α * β) → β → β (e) ∀αβγ. (α * (β → α → γ)) → (α → β) → γ Aufgabe 2.3 (Typschema 2 ) Geben Sie die Typschemata folgender Bezeichner an: (a) val a = fn x ⇒ ( fn y ⇒ if y then x else 3) (b) val b = fn x ⇒ ( fn y ⇒ ( fn f ⇒ f (x , y ) true )) (c) val c = let fun f x y = if x then y else 2 in ( fn t ⇒ fn s ⇒ ( f s t ,())) end Aufgabe 2.4 (Bezeichnerbindungen) Bereinigen Sie folgende Prozedurdeklaration: Überstreichen Sie die definierenden Bezeichnerauftreten, stellen Sie die lexikalischen Bindungen mit Pfeilen dar und benennen Sie konsistent die gebundenen Bezeichner um. fun g x y = ( fn x ⇒ let val x = f x val y = g x y in x + y end ) x 1 Aufgabe 2.5 (Bindungsprobleme) Bereinigen Sie das folgende Programm durch Überstreichen der definierenden und Indizieren der gebundenen Bezeichnerauftreten. val fun val fun (x , y ) = (2 ,3) f x = fn x ⇒ #1( x , y ) y = x*y g g = f x g Machen Sie sich zunächst klar, wie die Deklaration der Prozedur g zu verstehen ist. Kaskadierte und Höherstufige Prozeduren Aufgabe 2.6 (Konstant) Schreiben Sie eine Prozedur constant: α → β → α nach Möglichkeit auf drei verschiedene Weisen: kaskadiert, mit einer lokalen Deklaration und mit einer Abstraktion. Die Prozedur soll immer konstant das erste Argument zurückgeben, egal was als zweites Argument eingegeben wird. Aufgabe 2.7 (Kaskadiert und höherstufig) Schreiben Sie folgende Prozeduren: (a) eine höherstufige Prozedur, die nicht kaskadiert ist. (b) eine kaskadierte Prozedur, die nicht höherstufig ist. (c) eine höherstufige, kaskadierte Prozedur. Aufgabe 2.8 (Konvertieren) Schreiben Sie zwei Prozeduren (a) cas: (int * int → int) → int → int → int (b) car: (int → int → int) → int * int → int so, dass cas zur kartesischen Darstellung einer zweistelligen Operation die kaskadierte Darstellung und car zur kaskadierten Darstellung die kartesische Darstellung liefert. Aufgabe 2.9 (Höherstufiges Produkt) Deklarieren Sie eine Prozedur prod: (int → int) → int → int, die für n > 0 die Gleichung prod f n = 1·(f 1)·. . .·(f n) erfüllt. Deklarieren Sie außerdem mithilfe von prod eine Prozedur fac: int → int, die für n > 0 die Fakultät n! berechnet. Aufgabe 2.10 (Primzahlen 1 ) Deklarieren Sie zunächst eine Prozedur forall: int → int → (int → bool) → bool, sodass forall m n p genau dann true liefert, wenn p für alle natürlichen Zahlen von m bis n (inklusive) das Ergebnis true liefert. Verwenden Sie andalso und orelse. Schreiben Sie anschließend mithilfe von forall eine Prozedur isprime: int → bool, die testet, ob eine Zahl x eine Primzahl ist. Aufgabe 2.11 (Wahrheitszähler) Schreiben Sie eine Prozedur tcount: int → int → (int → bool) → int, welche zu zwei Zahlen n, m > 0 die Anzahl der Zahlen v mit n ≤ v ≤ m berechnet, für die eine Prozedur p den Wert true ergibt. Verwenden Sie eine endrekursive Hilfsprozedur tcount’. Die Prozedur tcount selbst soll nicht rekursiv sein. Deklarieren Sie außerdem mithilfe von tcount eine Prozedur pcount: int → int, die zählt, wieviele Zahlen kleinergleich n Primzahlen sind. 2 Iter und First Aufgabe 2.12 (Primzahlen 2 ) Schreiben Sie unter Verwendung der Prozedur isprime aus Aufgabe 2.10 folgende Prozeduren: (a) nextprime: int → int, sodass nextprime zu einer Zahl n die erste Primzahl x > n liefert. (b) nthprime: int → int, die für n ≥ 1 die n-te Primzahl liefert. Aufgabe 2.13 (Iter Rocks) Deklarieren Sie folgende Prozeduren mithilfe von iter: (a) add: int → int → int, die zwei Zahlen x, y durch Inkrementieren addiert. (b) power: int → int → int, zur Berechnung von Potenzen. (c) sum: int → (int → α) → α, sodass sie für n ≥ 0 die Gleichung sum n f = 0 + f 1 + ... + f n erfüllt. Benutzen Sie Tupel und eine Projektion. Aufgabe 2.14 (Fakultät) Deklarieren Sie n! mit iterup. Aufgabe 2.15 (Gerade oder ungerade) Schreiben Sie eine Prozedur gerade: int → bool, die für eine Zahl n prüft, ob sie gerade oder ungerade ist. Verwenden Sie dazu ausschließlich iter und weder die Operation mod noch div. Aufgabe 2.16 (Summe) Schreiben Sie eine Prozedur gsum: int → int → int, die zu zwei natürlichen Zahlen m, n mit m < n die Summe m + (m + 1) + . . . + (n − 1) + n berechnet. Verwenden Sie dabei folgende Prozeduren: (a) iterup (b) iter Aufgabe 2.17 (Think Diverent) Schreiben Sie die Prozedur div zur ganzzahligen Division auf folgende alternative Weisen: (a) fdiv: int → int → int, mithilfe von first. (b) idiv: int → int → int, mithilfe von iter. Hinweis: Verwenden Sie Tupel und eine Projektion für Aufgabenteil b). Aufgabe 2.18 (First erweitern) Deklarieren Sie folgende Prozeduren: (a) eine Prozedur second: (α → true) → int, die die zweite Zahl x > 0 findet, für die eine Prozedur p den Wert true ergibt. Verwenden Sie first. (b) eine Prozedur, die allgemein die k-te Zahl findet, für die eine Prozedur p true ergibt. Aufgabe 2.19 (Iter erweitern) Deklarieren Sie mithilfe der Prozedur iter eine Prozedur: (a) iterup’, die zu m, n, s, und f dasselbe Ergebnis liefert wie iterup m n s f. (b) iterdn’, die zu m, n, s, und f dasselbe Ergebnis liefert wie iterdn m n s f. 3