diff --git a/Übungen/Blatt1.hs b/Übungen/Blatt1.hs index 2397685..85e1ef4 100644 --- a/Übungen/Blatt1.hs +++ b/Übungen/Blatt1.hs @@ -1,11 +1,11 @@ -{- +{- Übungsblatt 1 ============= Typtheorie ---------- -Schreiben sie alle **möglichen** Implementationen der folgenden +Schreiben Sie alle **möglichen** Implementationen der folgenden Funktionen. Wozu könnte `fun2` nützlich sein? -} @@ -18,61 +18,71 @@ 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.-} +{- +Wir haben in der Vorlesung parametrisierte Typen kennengelernt. Der +simpelste hiervon ist `Identity`, der 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 -} +Schreiben Sie die Funktion +-} unIdentity :: Identity a -> a unIdentity = _unIdentity -{- welche diesen Vorgang wieder rückgängig macht. +{- +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` +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-} +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? +{- +**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 -Datentypen-} +Datentypen können auch Funktionen enthalten. Sehen Sie sich einmal den +Datentypen +-} data Pred a = Pred (a -> Bool) -{- an. Hier wird ein Prädikat definiert, welches (gegeben einen Datentyp +{- +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-} +Auch hier können Sie 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?). +{- +Da Haskell-Funktionen aber "gecurried" sind (mehr dazu in der +Vorlesung), 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?-} +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 @@ -82,26 +92,29 @@ 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. +von eigenen Datentypen. Zur Erinnerung; es gibt zwei Möglichkeiten, die +man miteinander kombinieren kann: `data Prod a b c = Prod a b c` +(Produkttyp) benötigt sowohl `a`, `b` als auch `c` um einen Wert zu +erzeugen, `data Sum a b = Sum1 a | Sum2 b` (Summentyp) 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` +Definieren Sie einen Datentypen `Vielleicht a`, der zwei Konstruktoren +besitzt: Einen Konstruktor, mit dem durch ein `a` ein `Vielleicht a` konstruiert wird und ein zweiter Konstruktor, der keinen Wert nimmt, -sondern die "Abwesenheit eines `a`" symbolisieren soll.-} +sondern die "Abwesenheit eines `a`" symbolisieren soll. +-} data Vielleicht a = Exercise -{- Können sie hier eine Funktion schreiben, die das `a` extrahiert? Wenn -ja, implementieren sie diese; wenn nein, geben sie eine kurze +{- +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-} +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 @@ -111,5 +124,5 @@ 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? +`Vielleicht (Pred a)`? Oder sind diese identisch? -} diff --git a/Übungen/Blatt1.lhs b/Übungen/Blatt1.lhs index 981f582..21306ac 100644 --- a/Übungen/Blatt1.lhs +++ b/Übungen/Blatt1.lhs @@ -4,7 +4,7 @@ Typtheorie ---------- -Schreiben sie alle **möglichen** Implementationen der folgenden +Schreiben Sie alle **möglichen** Implementationen der folgenden Funktionen. Wozu könnte `fun2` nützlich sein? > fun1 :: a -> a @@ -17,36 +17,35 @@ Funktionen. Wozu könnte `fun2` nützlich sein? > 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. +simpelste hiervon ist `Identity`, der 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 +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` +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 +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? +implementieren. Kommen Sie auf beide? Funktionen sind auch nur Typen ------------------------------ -Datentypen können auch Funktionen enthalten. Sehen sie sich einmal den -Datentype +Datentypen können auch Funktionen enthalten. Sehen Sie sich einmal den +Datentypen > data Pred a = Pred (a -> Bool) @@ -55,22 +54,22 @@ an. Hier wird ein Prädikat definiert, welches (gegeben einen Datentyp 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 +Auch hier können Sie 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?). +Da Haskell-Funktionen aber "gecurried" sind (mehr dazu in der +Vorlesung), 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? +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 @@ -79,26 +78,26 @@ 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. +von eigenen Datentypen. Zur Erinnerung; es gibt zwei Möglichkeiten, die +man miteinander kombinieren kann: `data Prod a b c = Prod a b c` +(Produkttyp) benötigt sowohl `a`, `b` als auch `c` um einen Wert zu +erzeugen, `data Sum a b = Sum1 a | Sum2 b` (Summentyp) 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` +Definieren Sie einen Datentypen `Vielleicht a`, der zwei Konstruktoren +besitzt: Einen Konstruktor, mit dem durch ein `a` ein `Vielleicht a` konstruiert wird und ein zweiter Konstruktor, der keinen Wert nimmt, sondern die "Abwesenheit eines `a`" symbolisieren soll. > data Vielleicht a = Exercise -Können sie hier eine Funktion schreiben, die das `a` extrahiert? Wenn -ja, implementieren sie diese; wenn nein, geben sie eine kurze +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 +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 @@ -107,6 +106,4 @@ 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? - -> main = putStrLn "compiles" +`Vielleicht (Pred a)`? Oder sind diese identisch? diff --git a/Übungen/Blatt1.pdf b/Übungen/Blatt1.pdf index 21719ae..20c923d 100644 Binary files a/Übungen/Blatt1.pdf and b/Übungen/Blatt1.pdf differ