Schönheitswettbewerb
bearbeitet von 1unitedpower> > Zusätzlich hat die Haskell-Definition mit weniger Worten mehr zum Ausdruck gebracht: Die Funktion `f1` ist typsicher, wenn sie mit einem String oder einem beliebigem nicht numerischen Wert aufgerufen wird, gibt es einen Typfehler zur Compilezeit. Außerdem funktioniert die Haskell-Variante ohne weiteres Zutun auch mit unbeschränkt großen Zahlen und beliebig genauen reellen Zahlen.
>
> Wobei man dies natürlich nicht aus `f1 = (*)`{: .language-haskell} herauslesen kann.
Das stimmt, das zu sehen erfordert Haskell-Vorwissen, ich hätte den Typen auch ausschreiben können, um es explizit zu machen.
~~~haskell
f1 :: Int -> (Int -> Int)
f1 = (*)
~~~
Die Typsignatur drückt folgendes aus: „f1 ist eine Funktion, die einen Int-Wert entgegen nimmt und eine Funktion zurück gibt, die ebenfalls einen Int-Wert entgegen nimmt und einen Int-Wert zurück liefert“. Das Klammernpaar in der Typsignatur hätte ich auch Weglassen können, weil der Pfeil rechts-assoziativ ist, also:
~~~haskell
f1 :: Int -> Int -> Int
~~~
Der Typ ist jetzt allerdings spezifischer als er sein müsste, weil die Funktion nicht nur mit Int-Werten arbeiten kann, sondern mit allen numerischen Typen, die eine Multiplikation unterstützen, u.a. auch Fließkommazahlen und die reellen Zahlen. Diese Datentypen werden Haskell in einer sogenannten Typklasse `Num a` gesammelt, wobei das `a` stellvertetend für einen Typen steht. Wenn ein Typ zu dieser Typklasse gehört, sagt man auch der Typ hat eine Instanz von der Typklasse `Num a`. Der Int-Typ hat beispielsweise so eine Instanz, und ebenso die ganzen und rellen Zahlen. Man kann Typklassen in Haskell als Nebenbedingung in Typsignaturen benutzen. Zum Beispiel kann ich die Signatur von `f1` jetzt so auflockern, dass sie mit allen numerischen Typen funktioniert:
~~~haskell
f1 :: forall a . Num a => a -> a -> a
~~~
Die Lesart ist: „Für alle Typen `a`, die eine Instanz von `Num a` haben, lass `f1` eine Funktion sein, die ein `a` als Parameter hat, und eine Funktion zurückliefert, die wiederum ein `a` als Parameter hat und schließlich ein `a` zurück gibt“. Das `forall a .` ist optional in Haskell, nicht quantifizierte Typvariablen werden automatisch all-quantifiziert.
Eine Stärke von Haskell ist, dass man Typsignaturen nur in extrem seltenen Ausnahmefällen angeben muss, im vorliegenden Fall assoziiert Haskell `f1` automatisch mit genau diesem letzten Typen. Noch besser ist, dass man sich während der Entwicklung anzeigen lassen, welchen Typen Haskell einem bestimmten Ausdruck zuordnet. Das Typsystem will sich dem Entwickler nicht aufdrängen, sondern ihn vor Fehlern bewahren, dazu ist es nicht notwenig den Typen auszuschreiben, es ist nur notwendig, dass der Typchecker den Programmierer mit Typinformationen versorgen kann. In vielen Programmiersprachen ist das andersrum, da hilft der Programmierer dem Compiler.
Schönheitswettbewerb
bearbeitet von 1unitedpower> > Zusätzlich hat die Haskell-Definition mit weniger Worten mehr zum Ausdruck gebracht: Die Funktion `f1` ist typsicher, wenn sie mit einem String oder einem beliebigem nicht numerischen Wert aufgerufen wird, gibt es einen Typfehler zur Compilezeit. Außerdem funktioniert die Haskell-Variante ohne weiteres Zutun auch mit unbeschränkt großen Zahlen und beliebig genauen reellen Zahlen.
>
> Wobei man dies natürlich nicht aus `f1 = (*)`{: .language-haskell} herauslesen kann.
Das stimmt, das zu sehen erfordert Haskell-Vorwissen, ich hätte den Typen auch ausschreiben können, um es explizit zu machen.
~~~haskell
f1 :: Int -> (Int -> Int)
f1 = (*)
~~~
Die Typsignatur drückt folgendes aus: „f1 ist eine Funktion, die einen Int-Wert entgegen nimmt und eine Funktion zurück gibt, die ebenfalls einen Int-Wert entgegen nimmt und einen Int-Wert zurück liefert“. Das Klammernpaar in der Typsignatur hätte ich auch Weglassen können, weil der Pfeil rechts-assoziativ ist, also:
~~~haskell
f1 :: Int -> Int -> Int
~~~
Der Typ ist jetzt allerdings spezifischer als er sein müsste, weil die Funktion nicht nur mit Int-Werten arbeiten kann, sondern mit allen numerischen Typen, die eine Multiplikation unterstützen, u.a. auch Fließkommazahlen und die reellen Zahlen. Diese Datentypen werden Haskell in einer sogenannten Typklasse `Num a` gesammelt, wobei das `a` stellvertetend für einen Typen steht. Wenn ein Typ zu dieser Typklasse gehört, sagt man auch der Typ hat eine Instanz von der Typklasse `Num a`. Der Int-Typ hat beispielsweise so eine Instanz, und ebenso die ganzen und rellen Zahlen. Man kann Typklassen in Haskell als Nebenbedingung in Typsignaturen benutzen. Zum Beispiel kann ich die Signatur von `f1` jetzt so auflockern, dass sie mit allen numerischen Typen funktioniert:
~~~haskell
f1 :: forall a . Num a => a -> a -> a
~~~
Die Lesart ist: „Für alle Typen `a`, die eine Instanz von `Num` haben, lass `f1` eine Funktion sein, die ein `a` als Parameter hat, und eine Funktion zurückliefert, die wiederum ein `a` als Parameter hat und schließlich ein `a` zurück gibt“. Das `forall a .` ist optional in Haskell, nicht quantifizierte Typvariablen werden automatisch all-quantifiziert.
Eine Stärke von Haskell ist, dass man Typsignaturen nur in extrem seltenen Ausnahmefällen angeben muss, im vorliegenden Fall assoziiert Haskell `f1` automatisch mit genau diesem letzten Typen. Noch besser ist, dass man sich während der Entwicklung anzeigen lassen, welchen Typen Haskell einem bestimmten Ausdruck zuordnet. Das Typsystem will sich dem Entwickler nicht aufdrängen, sondern ihn vor Fehlern bewahren, dazu ist es nicht notwenig den Typen auszuschreiben, es ist nur notwendig, dass der Typchecker den Programmierer mit Typinformationen versorgen kann. In vielen Programmiersprachen ist das andersrum, da hilft der Programmierer dem Compiler.
Schönheitswettbewerb
bearbeitet von 1unitedpower> > Zusätzlich hat die Haskell-Definition mit weniger Worten mehr zum Ausdruck gebracht: Die Funktion `f1` ist typsicher, wenn sie mit einem String oder einem beliebigem nicht numerischen Wert aufgerufen wird, gibt es einen Typfehler zur Compilezeit. Außerdem funktioniert die Haskell-Variante ohne weiteres Zutun auch mit unbeschränkt großen Zahlen und beliebig genauen reellen Zahlen.
>
> Wobei man dies natürlich nicht aus `f1 = (*)`{: .language-haskell} herauslesen kann.
Das stimmt, das zu sehen erfordert Haskell-Vorwissen, ich hätte den Typen auch ausschreiben können, um es explizit zu machen.
~~~haskell
f1 :: Int -> (Int -> Int)
f1 = (*)
~~~
Die Typsignatur drückt folgendes aus: „f1 ist eine Funktion, die einen Int-Wert entgegen nimmt und eine Funktion zurück gibt, die ebenfalls einen Int-Wert entgegen nimmt und einen Int-Wert zurück liefert“. Das Klammernpaar in der Typsignatur hätte ich auch Weglassen können, weil der Pfeil rechts-assoziativ ist, also:
~~~haskell
f1 :: Int -> Int -> Int
~~~
Der Typ ist jetzt allerdings spezifischer als er sein müsste, weil die Funktion nicht nur mit Int-Werten arbeiten kann, sondern mit allen numerischen Typen, die eine Multiplikation unterstützen, u.a. auch Fließkommazahlen und die reellen Zahlen. Diese Datentypen werden Haskell in einer sogenannten Typklasse `Num a` gesammelt, wobei das `a` eine stellvertetend für einen Typen steht. Wenn ein Typ zu dieser Typklasse gehört, sagt man auch der Typ hat eine Instanz von der Typklasse `Num a`. Der Int-Typ hat beispielsweise so eine Instanz, und ebenso die ganzen und rellen Zahlen. Man kann Typklassen in Haskell als Nebenbedingung in Typsignaturen benutzen. Zum Beispiel kann ich die Signatur von `f1` jetzt so auflockern, dass sie mit allen numerischen Typen funktioniert:
~~~haskell
f1 :: forall a . Num a => a -> a -> a
~~~
Die Lesart ist: „Für alle Typen `a`, die eine Instanz von `Num` haben, lass `f1` eine Funktion sein, die ein `a` als Parameter hat, und eine Funktion zurückliefert, die wiederum ein `a` als Parameter hat und schließlich ein `a` zurück gibt“. Das `forall a .` ist optional in Haskell, nicht quantifizierte Typvariablen werden automatisch all-quantifiziert.
Eine Stärke von Haskell ist, dass man Typsignaturen nur in extrem seltenen Ausnahmefällen angeben muss, im vorliegenden Fall assoziiert Haskell `f1` automatisch mit genau diesem letzten Typen. Noch besser ist, dass man sich während der Entwicklung anzeigen lassen, welchen Typen Haskell einem bestimmten Ausdruck zuordnet. Das Typsystem will sich dem Entwickler nicht aufdrängen, sondern ihn vor Fehlern bewahren, dazu ist es nicht notwenig den Typen auszuschreiben, es ist nur notwendig, dass der Typchecker den Programmierer mit Typinformationen versorgen kann. In vielen Programmiersprachen ist das andersrum, da hilft der Programmierer dem Compiler.
Schönheitswettbewerb
bearbeitet von 1unitedpower> > Zusätzlich hat die Haskell-Definition mit weniger Worten mehr zum Ausdruck gebracht: Die Funktion `f1` ist typsicher, wenn sie mit einem String oder einem beliebigem nicht numerischen Wert aufgerufen wird, gibt es einen Typfehler zur Compilezeit. Außerdem funktioniert die Haskell-Variante ohne weiteres Zutun auch mit unbeschränkt großen Zahlen und beliebig genauen reellen Zahlen.
>
> Wobei man dies natürlich nicht aus `f1 = (*)`{: .language-haskell} herauslesen kann.
Das stimmt, das zu sehen erfordert Haskell-Vorwissen, ich hätte den Typen auch ausschreiben können, um es explizit zu machen.
~~~haskell
f1 :: Int -> (Int -> Int)
f1 = (*)
~~~
Die Typsignatur drückt folgendes aus: „f1 ist eine Funktion, die einen Int-Wert entgegen nimmt und eine Funktion zurück gibt, die ebenfalls einen Int-Wert entgegen nimmt und einen Int-Wert zurück liefert“. Das Klammernpaar in der Typsignatur hätte ich auch Weglassen können, weil der Pfeil rechts-assoziativ ist, also:
~~~haskell
f1 :: Int -> Int -> Int
~~~
Der Typ ist jetzt allerdings spezifischer als er sein müsste, weil die Funktion nicht nur mit Int-Werten arbeiten kann, sondern mit allen numerischen Typen, die eine Multiplikation unterstützen, u.a. auch die reellen Zahlen. Diese Datentypen werden Haskell in einer sogenannten Typklasse `Num a` gesammelt, wobei das `a` eine stellvertetend für einen Typen steht. Wenn ein Typ zu dieser Typklasse gehört, sagt man auch der Typ hat eine Instanz von der Typklasse `Num a`. Der Int-Typ hat beispielsweise so eine Instanz, und ebenso die ganzen und rellen Zahlen. Man kann Typklassen in Haskell als Nebenbedingung in Typsignaturen benutzen. Zum Beispiel kann ich die Signatur von `f1` jetzt so auflockern, dass sie mit allen numerischen Typen funktioniert:
~~~haskell
f1 :: forall a . Num a => a -> a -> a
~~~
Die Lesart ist: „Für alle Typen `a`, die eine Instanz von `Num` haben, lass `f1` eine Funktion sein, die ein `a` als Parameter hat, und eine Funktion zurückliefert, die wiederum ein `a` als Parameter hat und schließlich ein `a` zurück gibt“. Das `forall a .` ist optional in Haskell, nicht quantifizierte Typvariablen werden automatisch all-quantifiziert.
Eine Stärke von Haskell ist, dass man Typsignaturen nur in extrem seltenen Ausnahmefällen angeben muss, im vorliegenden Fall assoziiert Haskell `f1` automatisch mit genau diesem letzten Typen. Noch besser ist, dass man sich während der Entwicklung anzeigen lassen, welchen Typen Haskell einem bestimmten Ausdruck zuordnet. Das Typsystem will sich dem Entwickler nicht aufdrängen, sondern ihn vor Fehlern bewahren, dazu ist es nicht notwenig den Typen auszuschreiben, es ist nur notwendig, dass der Typchecker den Programmierer mit Typinformationen versorgen kann. In vielen Programmiersprachen ist das andersrum, da hilft der Programmierer dem Compiler.