2012-03-30 14 views
1

Gestatten Sie mir zu teilen, was ich bisher haben zu starten:Laden/Ändern/Speichern von Änderungen in Textdatei

main :: IO() 
main = do contents <- readFile "filmList.txt" 
     let database = (read contents :: [Film]) 
     putStr "Please enter your username: " 
     userName <- getLine 
     menu database   
     where menu newDb = do putStrLn "\nPlease select an option:" 
          putStrLn "1: Display all films currently in the database" 
          putStrLn "2: Add a new film to the database (and display all films)" 
          putStrLn "3: " 
          putStrLn "4: Save Database" 
          putStrLn "5: Exit" 
          putStr "\nSelected option: " 
          option <- getLine 
          case option of "1" -> putStrLn(displayFilms newDb) 
              "2" -> do putStr "Name of film: " 
                title <- getLine 
                putStr "Name of director: " 
                director <- getLine 
                putStr "Year of release: " 
                year <- getLine 
                putStrLn(displayFilms (addNewFilm title director (read year) newDb)) 
          menu newDb 

`

ich es geschafft haben, eine TXT-Datei mit der Datenbank von Filmtypen zu laden aber ich kann nicht herausfinden, wie man Änderungen an den Daten vornimmt. Wenn ich Option 2 starte, erhalte ich eine Liste aller Filme mit dem neu hinzugefügten Film, aber wenn ich dann Option 1 benutze, um alle Filme aufzulisten, wird der neu hinzugefügte Film nicht berücksichtigt. Soll ich jedes Mal, wenn eine neue Film-Instanz hinzugefügt wird, wieder in die TXT-Datei speichern? Jede Hilfe wird sehr geschätzt, danke!

Antwort

4

Denken Sie daran, dass alles in Haskell unveränderlich ist. Wenn Sie addNewFilm (addNewFilm title director (read year) newDb schreiben, ändert das die Datenbank, die von newDb dargestellt wird, um die neue Information zu enthalten; es gibt nur eine neue Datenbank zurück, die alle alten Informationen plus die neue Zeile enthält. Es liegt in Ihrer Verantwortung zu wählen, wo und wann die alte Datenbank (ironisch newDb genannt) oder die neue von der Funktion zurückgegebene Datenbank verwendet werden soll.

Zum Beispiel könnten Sie diese case stattdessen schreiben:

case option of "1" -> putStrLn (displayFilms newDb) >> menu newDb 
       "2" -> do ... 
         let evenMoreReallyNewDb = addNewFilm title director (read year) newDb 
         putStrLn (displayFilms evenMoreReallyNewDb) 
         menu evenMoreReallyNewDb 

Sie können feststellen, dass in beiden Fällen mit einem sehr ähnlichen Muster enden (ein putStrLn . displayFilms und dann ein menu). Sie zu vereinheitlichen wäre eine gute Idee; Sehen Sie, ob Sie selbst sehen können, wie Sie das machen.

Wenn Sie die geänderte Datenbank zurück in die Datei schreiben möchten, müssen Sie dies natürlich explizit mit writeFile oder einer ähnlichen Funktion tun.

+0

Danke Daniel, ich habe es geschafft, dieses Problem jetzt zu lösen, und bin in der Lage, in txt-Datei auch schön zu speichern. Ich habe jedoch nachgedacht, was Sie über die Vereinheitlichung des repetitiven Codes gesagt haben. Wie würdest du mir empfehlen, das zu tun? Ich kann scheinbar nichts Nützliches online finden. Vielleicht muss ich an den richtigen Stellen suchen. Können Sie mir dazu einen Rat geben? Ich schätze es sehr. Vielen Dank. –

+1

@KieranEdwards Erwägen Sie, eine andere Funktion 'menuWithPrint db = putStrLn (displayFilms db) >> menu db' zu definieren und diese aufzurufen, anstatt den Code in beiden Zweigen zu duplizieren. –

+1

Wenn Sie in Zukunft mehr idiomatischen Code schreiben möchten, erfahren Sie mehr über Monad-Transformatoren. Ihr Code wäre viel einfacher, wenn Sie die 'StateT [Film] IO()' Monade verwenden würden. Zuerst müssen Sie etwas über die [Staatsmonde] erfahren (http://mvanier.livejournal.com/5406.html) und dann etwas über [Monad Transformer] erfahren (http://www.grabmueller.de/martin/www/pub) /Transformers.pdf). –