Abstrakte Datentypen und das Typsystem von Haskell

... [Seminar "Funktionale Programmierung"] ... [Inhaltsübersicht] ... [Typinferenz] ... [Literaturliste] ...


7. Abstrakte Datentypen


7.1. Modulkonzept

Ziel von abstrakten Datentypen ist es den konkreten Datentyp vor der Außenwelt und vor direkter Manipulation zu schützen. Der Zugriff auf einen solchen geschieht über eine definierte Schnittstelle, die aus einer Reihe von Zugriffsfunktionen besteht. Der Vorteil ergibt sich daraus, dass sich diese Abstrakten Datentypen auf unterschiedliche Art und Weise implementieren lassen und, da sie ja über eine gemeinsame Schnittstelle verfügen, sich nach Bedarf austauschen lassen. Der Applikation, welche den abstrakten Datentyp verwendet, bleibt ein solcher Austauch völlig verborgen. Abstrakte Datentypen werden in Haskell mit Hilfe des Modulkonzeptes realisiert.

Die modul-Deklaration ermöglicht es, mir ein solches Modul zu erstellen. Bei der Deklaration kann angegeben werden, welche Funktionen und welche Datentypen exportiert werden sollen, also dem Benutzer des Moduls zur Verfügung gestellt werden sollen.
module Tree (Tree (Leaf,Branch),fringe) where

data Tree a = Leaf a | Branch Tree a Tree a
fringe = ...

Dieses Modul hat den Namen Tree. Die Funktionen und Datentypen, welche exportiert werden, sind in der Klammer angegeben. Mit dem Datentyp Tree werden noch zusätzlich seine Daten-Konstruktoren Leaf und Branch exportiert. Wird die Klammer weggelassen, so wird alles exportiert.

Soll dieses Modul in einer Applikation verwendet werden, so wird das Modul mit der import -Deklaration geladen.

 module Main (main) where

import Tree (Tree(Leaf,Branch),fringe)
main = ...

Auch hier geben die Klammern an, welche Funktionen und Datentypen importiert werden sollen. Es kann nur das importiert werden, was das Modul selbst auch exportiert. Werden die Klammern weggelassen, so wird alles importiert, was vom Modul exportiert wurde.

Bei mehreren import-Deklarationen kann es vorkommen, dass es zu Namenskonflikten kommt. So könnten zwei Module Funktionen mit dem selben Namen exportieren. Um den Namenskonflikt zu verhindern und die Funktionen dennoch eindeutig ansprechen zu können, gibt es "Qualified Names". Der Modulname wird dabei, durch einen Punkt getrennt, vor die zu verwendene Funktion geschrieben.

module   Main where
import Tree ( Tree(Leaf,Branch), fringe )
import qualified Fringe ( fringe )

main = do print (fringe (Branch (Leaf 1) (Leaf 2)))
print (Fringe.fringe (Branch (Leaf 1) (Leaf 2)))
7.2. Erstellen eines abstrakten Datentyps

Um nun einen abstrakten Datentypen zu definieren, sollte zuerst ermittelt werden, an welcher Stelle in der Applikation ein solcher nötig ist und was genau alles gekapselt werden soll. Als Beispiel wird an dieser Stelle ein abstrakter Datentyp für einen Baum erstellt. Als nächstes sollte die Schnittstelle definiert werden, über die die Kommunikation mit dem abstrakten Datentyp geschieht. Es bietet sich an diese in Form von Typsignaturen zu notieren

data Tree a      -- Der Datentyp ohne Daten-Konstruktoren
leaf :: a -> Tree a
branch :: Tree a -> Tree a -> Tree a
cell :: Tree a -> a
left, right :: Tree a -> Tree a
isLeaf :: Tree a -> Bool

Daraus läßt sich nun auch der Modulkopf notieren. Der Datentyp Tree wird dabei ohne seine Daten-Konstruktoren exportiert, da auf Tree keine Manipulationen von der Applikation geschehen soll.

module TreeADT (Tree, leaf, branch, cell, left, right, isLeaf) where

Zum Schluß wird noch der Rumpf des Moduls notiert:

  data Tree a = Leaf a | Branch (Tree a) (Tree a) 

leaf x = Leaf x
branch x = Branch x
cell (Leaf a) = a
left (Branch l r) = l
right (Branch l r) = r
isLeaf (Leaf _) = True
isLeaf _ = False

Und fertig ist der abstrakte Datentyp.

Dies ist eine Applikation, welche diesen abstrakten Datentyp verwendet:

module Main(main) where
import TreeADT

aTree :: Tree Int
aTree = (branch (branch (leaf 5) (leaf 2)) (leaf 6))

leftOfMyTree :: Tree Int -> Tree Int
leftOfMyTree x = left x

main = leftOfMyTree aTree
Würde statt des Moduls TreeADT ein anderes mit gleicher Schnittstelle verwendet werden, so gäbe es für die Applikation keinen Unterschied.


... [Seminar "Funktionale Programmierung"] ... [Inhaltsübersicht] ... [Typinferenz] ... [Literaturliste] ...