1 Vorbemerkung 2 Listenoperationen (1+2+2+2 pt)

Werbung
------------------------------------------------------------------------ Seminar Theoretische Informatik
\ \
-- "Funktionale Programmierung mit Haskell"
\ \ ---- Universität Potsdam SS 2014
/ /\ --- Tim Richter / Mario Frank
/ / \
--- Übungsblatt 3 (Listen)
-- Abgabe bis: 28.05.2014, 23:59
-- Name:
-- Erreichte Punkte:
/ 14
---------------------------------------------------------------------module Uebung3 where
import Prelude
data Nat = O | S Nat deriving (Show )
intToNat
:: Int → Nat
intToNat n
| (n < 0) = ⊥
| (n ≡ 0) = O
| otherwise = S (intToNat (n − 1))
natToInt
:: Nat → Int
natToInt O
=0
natToInt (S n) = 1 + (natToInt n)
1
Vorbemerkung
Beweise sind stets im Stil des ”equational reasoning”, wie es im Buch eingeführt wird, zu führen. Insbesondere
ist für jede Gleichung in geschweiften Klammern hinter dem Gleichheitszeichen eine Begründung anzugeben.
Abweichung von dieser Form führt zu Punktverlust!
2
Listenoperationen (1+2+2+2 pt)
2.1
Last
Gegeben seien die folgenden Definitionen für die Funktion, die das letzte Element einer Liste zurückgibt:
last 0 (x : xs) = if null xs then x else last 0 xs
last 00 (x : xs) = if xs ≡ [ ] then x else last 00 xs
Der Unterschied zwischen last 0 und last 00 besteht darin, dass sich die Typen unterscheiden.
last 0 :: [a ] → a
last 00 :: (Eq a) ⇒ [a ] → a
Die Typ der Funktion last 00 beschränkt die Eingabe auf Listen von Elementen, die zum Typ Eq gehören.
Geben Sie einen Ausdruck n an, auf dem sich last 0 und last 00 unterschiedlich verhalten. (1 pt)
1
2.2
Verkettung
Beweisen Sie, dass folgende Gleichung gilt: (2 pt)
concat (xss ++ yss) = concat xss ++ concat yss
concat ist dabei als foldr (+
+) [ ] und (++) durch Rekursion über das erste Argument definiert (siehe Prelude). Schreiben Sie diese Definitionen aus und geben Sie den einzelnen Regeln Label, um im Beweis auf sie
referenzieren zu können!
2.3
Halbieren einer Liste
Definieren Sie eine Funktion
splitHalf :: [a ] → (([a ], [a ]), Maybe a)
splitHalf = ⊥
die eine Liste ”in der Mitte teilt”: Ist splitHalf as = ((bs, cs), m), so sollen die Listen bs und cs gleich lang
sein und es soll, falls m = Just a ist, as = bs ++ [a ] ++ cs und sonst as = bs ++ cs gelten. (2 pt)
2.4
Bedingtes Umkehren einer Liste
Definieren Sie eine Funktion
revEven :: [a ] → [a ]
revEven = ⊥
die alle Listen gerader Länge umkehrt und alle anderen Listen unverändert lässt. Benutzen Sie splitHalf und
”pattern guards” (siehe http://www.haskell.org/haskellwiki/Pattern_guard). Verwenden Sie weder
where noch let! (2 pt)
3
Map und Filter (1+1+2 pt)
3.1
Map
1. Geben Sie den Typen von map map an! (1 pt)
2. Beweisen Sie, dass folgende Gleichungen gelten:
map f (xs ++ ys) = map f xs ++ map f ys (1 pt)
map f . concat = concat . map (map f ) (2 pt)
Führen Sie den Beweis der zweiten Gleichung, indem Sie unter Benutzung der ersten Gleichung und
geeigneter Gesetze zeigen, dass beide Seiten sich als dieselbe foldr -Instanz schreiben lassen.
3.2
Filter (1 pt)
Die Prelude-Funktion filter :: (a → Bool ) → [a ] → [a ] kann mit Hilfe von concat und map konstruiert
werden:
filter 0 p = concat ◦ map box
where box x = ⊥
Vervollständigen Sie die Definition für box . (1 pt)
2
4
Folds (3 pt)
Die Funktionen takeWhile und dropWhile sind den Funktionen take und drop ähnlich. Statt eines Int-Indexes
nehmen sie jedoch einen Boole’schen Ausdruck als ersten Parameter. Das Ergebnis von
takeWhile p xs
ist das längste Initial-Segment von xs, dessen Elemente sämtlich die Bedingung p erfüllen. Zum Beispiel ist
takeWhile even [2,4,7,4,1,6] = [2,4]
1. Definieren Sie filter p als Instanz von foldr (1 pt)
2. Definieren Sie takeWhile als Instanz von foldr (1 pt)
3. Kann dropWhile als Instanz einer Fold-Funktion definiert werden? Implementieren oder begründen Sie!
(1 pt)
5
Hyperoperationen (just for fun)
Ausgehend von der Beobachtung, dass Multiplikation ”iterierte Addition” und Potenzieren ”iteriertes Multiplizieren” ist, definiert man die Folge der Hyperoperation (siehe Wikipedia: http://en.wikipedia.org/
wiki/Hyperoperation). Definieren Sie unter Verwendung von foldr1 und foldNat
foldNat :: a → (a → a) → Nat → a
foldNat s f O = s
foldNat s f (S m) = f $ foldNat s f m
eine Funktion
hop :: Nat → Integer → Integer → Integer
hop = ⊥
derart, dass a‘hop n‘b für b > 1 das Ergebnis der Anwendung der (n+1)ten (sic!) Hyperoperation auf das
Paar (a, b) ist! Für b < 1 darf die Funktion undefiniert sein.
3
Herunterladen