2011-11-13 15 views
5

sample input/outputbłąd coraz Prelude.read: brak parse

jestem bardzo nowy w Haskell, napisałem kod szczegółów elementu i przeszukać szczegół dla każdej pozycji.

kod
type Code = Int 
type Name = String 
type Database = (Code,Name) 

textfile::IO() 
textfile = appendFile "base.txt" (show[(110,"B")]) 

poszukiwaniu

fun::IO() 
fun=do putStrLn"Please enter the code of the product" 
     x<-getLine 
     let y = read x :: Int 
     show1 y 

textshow::IO [Database] 
textshow= do x<-readFile "base.txt" 
      let y=read x::[Database] 
     return y 

show1::Code->IO() 
show1 cd= do o<-textshow 
      let d=[(x,y)|(x,y)<-o,cd==x] 
     putStr(show d) 

za, ale problemem jest to, że działa dobrze dla pojedynczych danych, jeśli mogę dołączyć kolejne dane, to pokazuje błąd Prelude.read: no parse gdy próbuję wyszukać przedmiot . Pomoc zostanie doceniona!

+0

Czy możesz dodać przykładowe dane wejściowe, które powodują problem? – ibid

+0

Mam przesłane przykładowe migawki, proszę spojrzeć na. –

+1

Występują również problemy z wcięciami w textshow i show1. Ale myślę, że to pokazuje problem. Odpowiadając wkrótce. – ibid

Odpowiedz

4

Twój problem jest w formacie pliku danych. Po jednym zastosowaniu textfile plik zawiera następujące elementy:

[(110,"B")] 

to dobrą listę, i to działa. Po drugim wykorzystania textfile plik zawiera następujące elementy:

[(110,"B")][(110,"B")] 

to nie jest dobra lista, a to się nie powiedzie. Można to zobaczyć w ghci:

*Main> read "[(110,\"B\")][(110,\"B\")]" :: [Database] 
*** Exception: Prelude.read: no parse 

To jasne, że read spodziewa jedną listę, a nie dwa wykazy następujących siebie.

Jeśli chcesz dołączyć do pliku zawierającego pojedynczą listę Haskell, musisz przeczytać plik, dołączyć do listy i zapisać nową listę w pliku jako zamiennik.

addToFileList :: (Read a, Show a) => FilePath -> a -> IO() 
addToFileList fp a = do olds <- readFile fp `catch` \e -> 
           if isDoesNotExistError e 
           then return "[]" 
           else ioError e 
         let oldl = read olds 
          newl = oldl ++ [a] 
          news = show newl 
         length news `seq` 
           writeFile fp news 

To jest trochę trudne, ponieważ z dwóch Tings:

  • readFile jest leniwy i writeFile do tego samego pliku może nie, chyba że jeden daje pewność, że cały plik został już czytać. W powyższej funkcji jest to rozwiązywane przez zapytanie o długość nowego napisu przed zapisaniem pliku (funkcja seq upewnia się, że długość jest obliczana przed rozpoczęciem operacji zapisu).
  • plik może nie istnieć, klauzula catch jest używana powyżej do obsługi tego wyjątkowego przypadku.