www.jammni.de

Logo - Kleiner Drache
Login
Username:

Passwort:

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

Logo - DracheHaskell-Forum

spooky

Gepostet:
10.05.2008 04:41

Wert von "Variable" ändern  
Hallo,

Ich stehe vor folgendem Problem: Ich würde gerne aus einer Datei etwas einlesen, mir diesen Wert in einer "Variable" speichern und anschließend durch Funktionen bearbeiten. Das Ganze soll dann als eine Art "Mini-Datenbank" funktionieren: ich lese die "Datenbank" ein ändere Werte und speichere sie wieder in die Datei zurück.

Das eigentliche Einlesen und Schreiben der Werte ist noch kein Problem (für Standardtypen). Mir ist auch klar, dass ich Monaden brauche um den Zustand und damit den Wert eines Objektes zu verändern. Aber eben mit diesen Monaden hab ich ein Problem. Ein einfaches Beispiel wie ich den Wert ändern kann wäre sehr hilfreich.

mfg spooky
Zum Seitenanfang    
 
Siracusa

Gepostet:
10.05.2008 07:13

   
Hallo spooky,

willkommen im Forum! Die Monade, die du hier benötigst, ist die IO-Monade. Das Besondere dieser Monade ist, hat man einmal einen Wert vom Typ IO a, kann man ihn nicht mehr in einen vom Typ a zurücktransformieren. Man kann also innerhalb einer einfachen Funktion nicht einfach eine IO-Aktion "zwischenschalten" und wieder ein einfaches Ergebnis zurückgeben. Allerdings kannst du innerhalb eines do-Blockes die Werte aus der Monade "herausholen" (mittels <-) und einfache Funktionen auf sie anwenden. Das Ergebnis des do-Blocks ist allerdings wiederum eine IO-Aktion. Man wird sie also nicht los. ;-)

Das Grundgerüst für dein Vorhaben sieht etwa so aus:
main :: IO ()
main = do
text <- leseDatei "datei.txt"
schreibeDatei "datei.txt" (textUmwandeln text)

-- oder eine main, die das gleiche macht:
main = do
text <- leseDatei "datei.txt"
let text' = textUmwandeln text
schreibeDatei "datei.txt" text'

-- Die Signaturen der anderen Funktionen
leseDatei :: Path -> IO String
textUmwandeln :: String -> String
schreibeDatei :: Path -> String -> IO ()

Im Modul Control.Monad findest du übrigens zahlreiche Funktionen zum Transformieren von Monaden.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
spooky

Gepostet:
16.05.2008 03:26

   
erstmal danke für die Antwort. Meine Intention war ursprünglich etwas anders, werd es jetzt aber wohl so machen (scheint auch intelligenter zu sein). Allerdings hat sich jetzt ein neues Problem ergeben:

Angenommen ich habe eine Datenstruktur wie


data Person = Kind String | Vater String Int String deriving Show


Diese kann ich auch ganz leicht in eine Datei speichern. Allerdings kann ich sie nicht wieder laden (beziehungsweise den Typ parsen). Das Problem ist also wie ich so einen Datentyp beziehungsweise den String parse und den Datentyp bekomme. Ich hab das Ganze jetzt vorerst einmal ohne aus der Datei laden probiert (also einfach direkt den String an eine Methode gegeben), allerdings komm ich nicht dahinter wie das geht. (hab mir Read und ReadS angesehen komm aber irgendwie nicht weiter)

Wie mach ich also sowas? Und ist es intelligent den Datentyp einfach so als String zu speichern oder würdet ihr den irgendwie anders repräsentieren?

mfg spooky
Zum Seitenanfang    
 
Siracusa

Gepostet:
16.05.2008 06:14

   
Hallo,

genau wie bei Show kannst du auch eine Instanz der Klasse Read automatisch ableiten lassen. Um einen String dann zu parsen gibt es die Funktion reads, die eine leere Liste zurückliefert, falls ein Fehler aufgetreten ist, und ein Paar von dem geparsten Wert und dem Reststring beim erfolgreichen Parsen. Hier ein einfaches Beispiel:

module Main () where

data Person = Kind String deriving (Show, Read)

lesePerson :: String -> Person
lesePerson s = case reads s of
[] -> error "Fehler beim Parsen!"
[(person, rest)] -> person


-- Beispielausgabe:
Main> lesePerson "Kind Francesca"

Program error: Fehler beim Parsen!

Main> lesePerson "Kind \"Francesca\""
Kind "Francesca" :: Person


Den Datentyp als String zu speichern hat seine Vor- und Nachteile. Direkt den Wert mit allen Datenbankeinträgen in einen String zu konvertieren und in die Datei zu schreiben geht schnell zu programmieren. Allerdings wird bei sehr vielen Einträgen die Dateigröße relativ groß und das Einlesen könnte aufgrund des Parsers etwas länger dauern (fällt bei deinem relativ einfachen Datentyp wohl nicht ins Gewicht, bei sehr komplizieren verschachtelten Datentypen könnte das bei großen Datenmengen schon eher zu einem Problem werden). Wenn du es etwas platzsparender bevorzugst, such doch mal bei Hackage (http://hackage.haskell.org/packages/archive/pkg-list.html) nach Serialisierungspaketen. Je nachdem wie umfangreich dein Projekt werden soll, mußt mal schauen, ob sich der Aufwand dann überhaupt lohnt. Der GHC speichert seine Paketverwaltungsdaten übrigens auch direkt als String, von daher ...


Viele Grüße,

Siracusa
Zum Seitenanfang