Vorlesung2016/Übungen/Blatt1.md

3.5 KiB

Übungsblatt 1

Typtheorie

Schreiben sie alle möglichen Implementationen der folgenden Funktionen. Wozu könnte fun2 nützlich sein?

fun1 :: a -> a
fun1 = _fun1

fun2 :: a -> b -> a
fun2 = _fun2

fun3 :: (Eq a) => a -> a -> Bool
fun3 = _fun3

Wir haben in der Vorlesung parametrisierte Typen kennengelernt. Der simpelste hiervon ist Identity, der genau gar nichts macht, sondern nur einen anderen Typen einpackt.

data Identity a = Identity a

Diese Definition stellt uns automatisch den Konstruktor Identity :: a -> Identity a zur Verfügung, der ein a einpackt. Schreiben sie die Funktion

unIdentity :: Identity a -> a
unIdentity = _unIdentity

welche diesen Vorgang wieder rückgängig macht.

Angenommen, sie hätten nun ein Wert vom Typen Identity a und eine Funktion mit dem Typen a -> b. Wie wenden sie diese auf das a "innerhalb" des Identity an um ein Identity b herzustellen? Schreiben sie also eine Funktion

mapIdentity :: (a -> b) -> Identity a -> Identity b
mapIdentity = _mapIdentity

Hinweis: Es gibt zwei prinzipielle Vorgehen dieses zu implementieren. Kommen sie auf beide?

Funktionen sind auch nur Typen

Datentypen können auch Funktionen enthalten. Sehen sie sich einmal den Datentype

data Pred a = Pred (a -> Bool)

an. Hier wird ein Prädikat definiert, welches (gegeben einen Datentyp a) eine Funktion gespeichert hat, die a in einen Bool umwandeln kann (etwa um irgendwas zu filtern/selektieren/löschen/..., wenn man dies an eine weitere Funktion übergibt).

Auch hier können sei eine Funktion schreiben, die das Pred a wieder "auspackt". Definieren sie

unPred :: Pred a -> (a -> Bool)
unPred = _unPred

Da Haskell-Funktionen aber "gecurried" sind, können sie die Klammern hinten in der Signatur auch weglassen und erhalten unPred :: Pred a -> a -> Bool, was man zugleich als "wende Pred a an, wenn du ein a bekommst" lesen kann. In der Tat sind beide Funktionen identisch (wieso?).

Bonus

Was für eine Funktion bräuchten sie um ein Pred a in ein Pred b umzuwandeln? Können sie diese Implementieren?

mapPred :: _fun -> Pred a -> Pred b
mapPred = _mapPred

Neue Typen erfinden

In Haskell ist ein zentraler Vorgehenspunkt das Definieren und Verwenden von eigenen Datentypen. Zur Erinnerung; es gibt 2 Möglichkeiten, die man miteinander kombinieren kann: data Prod a b c = Prod a b c benötigt sowohl a, b als auch c um einen Wert zu erzeugen, data Sum a b = Sum1 a | Sum2 b braucht entweder ein a um durch den Konstruktor Sum1 ein Sum a b zu erzeugen oder ein b um durch den Konstruktor Sum2 ein Sum a b zu erzeugen.

Definieren sie einen Datentypen Vielleicht a, der zwei Konstruktoren besitzt: Einen Konstruktor, der durch ein a ein Vielleicht a konstruiert wird und ein zweiter Konstruktor, der keinen Wert nimmt, sondern die "Abwesenheit eines a" symbolisieren soll.

Können sie hier eine Funktion schreiben, die das a extrahiert? Wenn ja, implementieren sie diese; wenn nein, geben sie eine kurze Begründung.

Wie würden sie mittels einer Funktion a -> b ein Vielleicht a in ein Vielleicht b wandeln? Implementieren sie

mapVielleicht :: (a -> b) -> Vielleicht a -> Vielleicht b
mapVielleicht = _mapVielleicht

Bonus

Man kann Typen natürlich auch Schachteln. Worin liegt eigentlich der Unterschied zwischen einem Pred (Vielleicht a) und einem Vielleicht (Pred a)? Oder sind diese Identisch?