www.jammni.de

Logo - Kleiner Drache
Login
Username:

Passwort:

Daten merken
Auto-Login
Registrieren
 
Online
niemand
 
Forumsuche
Suche nach:

Logo - DracheHaskell-Forum

MoijoMs

Gepostet:
27.01.2011 12:25

type "Objekt" instanzieren  
Hallo!
Ich habe mit type eine "Klasse" geschrieben und möchte nun die "Methoden" mithilfe einer Instanz testen, aber wie geht das?
Code sieht wie folgt aus:


type Woerterbuch = String -> String

empty :: Woerterbuch
empty w = "nicht gefunden"

insert :: String -> String -> Woerterbuch -> Woerterbuch
insert e u w(e1) = if e == e1 then u else w(e1)

remove :: String -> Woerterbuch -> Woerterbuch
remove e w (e1) = if e == e1 then "nicht gefunden." else w(e1)

lookup :: String -> Woerterbuch -> String
lookup e w = w(e)


Joa.. wie kann ich jetzt im Programmfenster ein Woerterbuch anlegen?
Vielen Dank im Vorraus!


Zum Seitenanfang    
 
Landei

Gepostet:
27.01.2011 17:01

   
Mit type definierst du nur einen Alias, z.B. um kompliziertere Typen abzukürzen, oder klarzumachen, was ein Typ "bedeutet" (also etwa Alter anstatt Int)

Auf der rechten Seite steht String -> String, also eine Funktion, die aus einem String-Argument einen anderen String macht. Jede Funktion, die das erfüllt, kann als "Wörterbuch" übergeben werden. Eine ganz einfache Art, so eine Funktion zu schreiben, wäre mit pattern matching:


en_de :: Woerterbuch
en_de "one" = "eins"
en_de "two" = "zwei"
en_de "three" = "drei"
en_de "four" = "vier"
en_de _ = "kenne ich nicht"


Damit kann man natürlich noch nicht einfügen oder entfernen, ich kann mir jetzt erst mal nicht vorstellen, wie das mit einer Funktion funktionieren soll. Viel logischer wäre, z.B. so etwas zu definieren:


type Woerterbuch= [(String,String)]

en_de :: Woerterbuch
en_de = [("one","eins"),("two","zwei"),("three","drei"),("four","vier")]


Dann wären die von dir aufgeführten Operation leicht auszuführen.
Zum Seitenanfang    
 
MoijoMs

Gepostet:
27.01.2011 18:28

   
Bin noch neu was Haskell angeht...

Testen könnte man die Funktionen beispielsweise mit
lookup "two" (remove "two" en_de)
oder
lookup "house" (insert "house" "Haus" en_de)


ahjo, danke!
Zum Seitenanfang    
 
Landei

Gepostet:
28.01.2011 10:17

   
Nochmal: Deine Definition
type Woerterbuch = String -> String
definiert Wörterbuch als eine Funktion (im Prinzip als lookup-Funktion). Eine Funkion kann man nicht "ändern", also sehe ich keinen Weg, damit insert oder remove zu realisieren. Für solche Operationen brauchst du irgendwelche Datenstrukturen.

"Klassen" im OO-Sinne gibt es in Haskell nicht. Wenn du Typklassen meinst, dann würden die ganz anders aussehen:


class Woerterbuch w where
insert :: String -> String -> w -> w
remove :: String -> w -> w
lookup :: String -> w -> String


Dann könnte man eine geeignete Datenstruktur zu einer Wörterbuch-Instanz machen:


newtype Dic = Dic [(String,String)]

instance Woerterbuch Dic where
insert key value (Dic dic) = Dic $ (key,value) : filter (\entry -> (fst entry) /= key) dic
remove key (Dic dic) = Dic $ filter (\entry -> (fst entry) /= key) dic
lookUp key (Dic []) = "nicht gefunden"
lookUp key (Dic ((k,v):xs)) | k == key = v
| otherwise = lookUp key (Dic xs)


Als ich versucht habe, [(String,String)] direkt als Instanz zu verwenden, hat der Compiler gespuckt, deshalb der zusätzliche Dic-newtype um das Ganze herum. Mit Compileroptionen (hier -XFlexibleInstances) wollte ich nicht rumspielen.
Zum Seitenanfang    
 
Landei

Gepostet:
28.01.2011 13:33

   
Aha, nach Rückfrage weiß ich jetzt, dass man, wenn man um obige Lösung mit newtype herumkommen will, wohl oder übel das FlexibleInstances Pragma braucht:

{-# LANGUAGE FlexibleInstances #-} -- als erstes in der Datei, noch vor module

...

class Woerterbuch w where
insert :: String -> String -> w -> w
remove :: String -> w -> w
lookUp :: String -> w -> String

instance Woerterbuch [(String,String)] where
insert key value dic = (key,value) : remove key dic
remove key dic = filter (\entry -> (fst entry) /= key) dic
lookUp key [] = "nicht gefunden"
lookUp key ((k,v):xs) | k == key = v
| otherwise = lookUp key xs


Hoffentlich wird dieses Verhalten bald in den Standard aufgenommen.
Zum Seitenanfang    
 
Siracusa

Gepostet:
28.01.2011 19:00

   
Eine Funkion kann man nicht "ändern", also sehe ich keinen Weg, damit insert oder remove zu realisieren.

Hat er/sie doch oben schon gemacht ;-) Wobei der Punkt hier ist, die vorhandene Funktion nicht zu ändern, sondern zu erweitern. Ein Wörterbuch lässt sich dann aus der Verkettung von solchen Funktionen erstellen:
> let buch = insert "one" "eins" . insert "two" "zwei" . insert "three" "drei" $ empty
> lookup "eins" buch
"nicht gefunden"
> lookup "one" buch
"eins"


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
Landei

Gepostet:
28.01.2011 20:42

   
Ah, da stand ich ziemlich auf dem Schlauch, und hätte mir den Originalcode genauer angucken müssen. Ich nehme alles zurück und behaupte das Gegenteil...

Na ja, wenigstens etwas über Typklassen gelernt, auch wenn es neben der Spur war.
Zum Seitenanfang