Funktionale Programmierung mit Haskell/ Datentypen im Eigenbau

Aus Wikibooks

Synonyme[Bearbeiten]

Typensynonyme sind nichts weiter als ein anderer Name für schon vorhandene Typen. Das folgende Beispiel benennt ein Tupel aus zwei Double-Werten um in einen Typ namens Vector2D. Der Zugriff auf die einzelnen Komponenten der Vektoren in der Funktion addV, die zwei Vektoren addiert, funktioniert wie bei anderen 2-Tupeln auch mit den Funktionen fst und snd:

Align=none
type Vector2D = (Double, Double)

addV :: Vector2D  -> Vector2D -> Vector2D
addV a b = (fst a + fst b, snd a + snd b)

Der Ergebnistyp ist dann ebenfalls vom Typ Vector2D, das stellt bereits die Typsignatur sicher:

Align=none ghci t0.hs

Main> let a = addV (1, 2) (3, 2)
Main> a
(4.0,4.0)
Main> :type a
a :: Vector2D
Main>

Aufzählung[Bearbeiten]

Strukturierter Typ[Bearbeiten]

Typ mit newtype[Bearbeiten]

Typen kann man auch mit newtype erzeugen, dann hat man ähnlich wie bei data einen komplett neuen Typ. Dieser Typ, hier am Beispiel eines 2D-Punktes, kann eine Methode erben, mit der er sich zeigen kann:

Align=none
newtype Punkt2D = P2D (Double, Double)
    deriving (Show)

getPX :: Punkt2D -> Double
getPX (P2D (a, b)) = a

getPY :: Punkt2D -> Double
getPY (P2D (a, b)) = b

deriving(Show) ist hierbei die Schreibweise dafür, dass der Compiler für unseren Typ eine geeignete Instanz der Typklasse Show herleiten soll, wodurch unser Typ anzeigbar wird:

Align=none ghci t4.hs

Main> let p = P2D (1, 3)
Main> p
P2D (1.0,3.0)
Main> getPX p
1.0
Main> getPY p
3.0
Main>

Diese Anzeige können wir anpassen, indem wir den Typ Show so modifizieren, dass er mit unserem Typ Punkt2D zusammenarbeitet. Show können wir dann so verändern, wie wir es wollen. Die Typenklasse Show enthält unter anderem eine Methode namens show, die wir anpassen können:

Align=none
newtype Punkt2D = P2D (Double, Double)

instance (Show Punkt2D) where
    show p = "Punkt2D Parameter: (" ++ show (getPX p) ++ ", " ++ show (getPY p) ++ ")"

getPX :: Punkt2D -> Double
getPX (P2D (a, b)) = a

getPY :: Punkt2D -> Double
getPY (P2D (a, b)) = b

Hier zeigen wir, wie sich die Änderung auswirkt:

Align=none ghci t4.hs

Main> let p = P2D (1, 3)
Main> p
Punkt2D Parameter: (1.0, 3.0)
Main>

Parametrisierter Typ[Bearbeiten]

Typen selbst kann man parametrisieren. Unsere obige Definition von Punkt2D kann sowohl mit Double wie auch mit Integer einen Punkt ergeben.

Align=none
newtype Vector2D d = V2D (d, d)

instance (Show a) => Show (Vector2D a) where
    show v = "Vector2D: Parameter: (" ++ show (getX v) ++ ", " ++ show (getY v) ++

getX :: Vector2D t -> t
getX (V2D (a, b)) = a

getY :: Vector2D t -> t
getY (V2D (a, b)) = b


Align=none ghci t5.hs

Main> let v = V2D (1, 2)
Main> :type v
v :: Vector2D Integer
Main> v
Vector2D: Parameter: (1, 2)
Main>

Anmerkungen[Bearbeiten]