Typklasse (Informatik)Typklassen sind ein Konstrukt der funktionalen Programmierung zur Implementierung von Ad-hoc-Polymorphie. Typklassen wurden für die Sprache Haskell entwickelt. Sie ähneln vom Prinzip her dem Konzept der Schnittstellen, haben aber nichts mit den Klassen der objektorientierten Programmierung zu tun. GeschichteTypklassen wurden ursprünglich entwickelt, um auf systematische Weise mathematische Operatoren zu überladen.[1] Der Ansatz erwies sich als sehr vielseitig, sodass man ihn schnell auch für andere Dinge, wie z. B. Monaden verwendete. Heutzutage sind Typklassen eines der wichtigsten Werkzeuge der Sprache Haskell und finden in fast allen Bereichen Anwendung, meist zur Definition von Schnittstellen oder Generalisierung von Bibliotheken. EinführungTypklassen definieren Funktionen, die für jede Instanz der Typklasse aufgerufen werden können. Man kann eine Instanz für jeden Typ erstellen, indem man die Funktionen der Typklasse für den jeweiligen Typ definiert. Ein einfaches Beispiel ist der Operator class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
a == b = not (a /= b)
a /= b = not (a == b)
Die Klasse definiert zwei Funktionen, die jeweils zwei Variablen vom Typ a, dem Parameter der Typklasse, als Argumente haben: Um eine Instanz einer Typklasse zu definieren, schreibt man folgendes (Hier am Beispiel von Typ instance Eq Bool where
True == True = True
False == False = True
_ == _ = False
Die Instanz überlädt nur die Funktion Der Clou ist nun, dass man nicht zu wissen braucht, um welchen Datentypen es sich handelt, um eine Funktion einer Typklasse auf ihn anzuwenden. Es genügt, dass eine Instanz der Typklasse vorhanden ist. Diese Information kann in Haskell über eine Erweiterung des Typsystems hinzugefügt werden. Hier zum Beispiel die Funktion nub :: Eq a => [a] -> [a]
nub [] = []
nub (x:xs) = x : nub (filter (/= x) xs)
VerwendungsbeispieleTypklassen werden in der Sprache Haskell für viele Zwecke verwendet, z. B.:
ImplementierungEs gibt mehrere Wege, Typklassen zu implementieren. Der ursprüngliche und in den meisten Implementationen, einschließlich des Glasgow Haskell Compiler, verwendete Implementation von Typklassen wird im Folgenden erklärt. Normalerweise implementiert man Typklassen, indem jede Typklasse durch einen Datentypen ersetzt wird. Er enthält als Felder die einzelnen Methoden der Typklasse. Wenn nun eine Funktion eine Instanz einer Typklasse für einen der Parameter benötigt, so wird ein Objekt des der gewünschten Typklasse zugehörigen Datentypes übergeben, welches die Instanz repräsentiert. Auf diese Weise wird für den endgültigen Code keine Erweiterung des bestehenden Typsystems benötigt. Man kann sich das am Beispiel der oben erwähnten Klasse Die Typklasse data Eq a = Eq (a -> a -> Bool) (a -> a -> Bool)
Für jede Instanz wird nun eine Variable vom Typ instanceEqBool :: Eq Bool
instanceEqBool = Eq eqBool (\a b -> not (eqBool a b)) where
eqBool True True = True
eqBool False False = True
eqBool _ _ = False
-- hier noch ein weiteres Beispiel: Der Einheitstyp ()
instanceEqUnit :: Eq ()
instanceEqUnit = Eq (\_ _ -> True) (\_ _ -> False)
Wenn jetzt eine Funktion den Kontext nub :: Eq a => [a] -> [a]
-- wird zu
nub :: Eq a -> [a] -> [a]
nub _ [] = []
nub (Eq _ (/=)) (x:xs) = x : nub (filter (/= x) xs)
Einzelnachweise
|
Portal di Ensiklopedia Dunia