type Typname (Parameter)* = Typ-AusdruckSie haben die gleichen Vor- und Nachteile wie Macros in C: bei sorgsamer Benutzung erhöhen sie die Übersichtlichkeit, aber der Compiler kann das nicht vom Programmierer erzwingen. Beispiel (SOE Seite 24)
type Radius = Float type Side = FloatDie Aussage Rectangle :: Side -> Side -> Shape sieht schön aus, aber Rectangle :: Float -> Radius -> Shape wird vom Compiler genauso akzeptiert.
Mit Typ-Synonymen können wir also Abstraktionen nicht wirklich durchsetzen. Das richtige Mittel dazu sind Algebraischen Datentypen, deren Konstruktoren nicht exportiert werden (siehe später mehr über Module).
data Typname (Parameter)* = ( Konstruktor { name :: Type, ... } )*Das erklärt wie oben eine Menge von Konstruktoren mit entsprechenden Typen und Stelligkeiten und zusätzlich eine Menge von Zugriffsfunktionen.
Beispiel (kompletter Quelltext)
type Winkel = Rational type Winkels = [ Winkel ] data Ecke = Ecke { sichtbar :: Winkel , alle :: Winkels } data Streckenzug = Streckenzug [ Ecke ]Ausdrücke vom Typ Ecke bauen wir so (Beispiel: reguläres Polygon?)
e :: Ecke e = Ecke { sichtbar = 1 % 2, alle = [ 1 % 2 ] }und wir können benannte Muster benutzen:
länge (Ecke { alle = ws }) = length wsDie Namen "sichtbar", "alle" sind auch Zugriffsfunktionen:
sichtbar :: Ecke -> Winkel alle :: Ecke -> WinkelsWir können (leider?) die Konstruktoren mit benannten Komponenten auch in der unbenannten Version benutzen.