2015-03-02 68 views
3

我有下面的記錄語法。Haskell記錄語法並從文件中讀取。字符串來記錄語法。 ***例外:Prelude.read:不解析

type Title = String 
type Author = String 
type Year = Int 
type Fan = String 


data Book = Book { bookTitle :: Title 
       , bookAuthor:: Author 
       , bookYear :: Year 
       , bookFans :: [Fan] 
       } 
       deriving (Show, Read) 


type Database = [Book] 

bookDatabase :: Database 
bookDatabase = [Book "Harry Potter" "JK Rowling" 1997 ["Sarah","Dave"]] 

我想創建一個讀取books.txt文件並將其轉換爲數據庫類型的IO函數。我認爲它需要與我下面的嘗試類似。

main :: IO() 
main = do fileContent <- readFile "books.txt"; 
      let database = (read fileContent :: Database) 

什麼是books.txt文件的正確格式?

以下是我目前的books.txt內容(與bookDatabase相同)。

[Book "Harry Potter" "JK Rowling" 1997 ["Sarah","Dave"]] 

***例外:Prelude.read:沒有解析

回答

6

的記錄只能讀取記錄語法派生Read實例。它無法讀取按順序應用於參數的構造函數格式的記錄。嘗試將以下(這是show bookDatabase的結果)放入books.txt

[Book {bookTitle = "Harry Potter", bookAuthor = "JK Rowling", bookYear = 1997, bookFans = ["Sarah","Dave"]}] 
-2

在您的示例中有幾件事需要解決。

首先,在您的數據類型聲明中,您需要派生一個Read實例。

data Book = Book { 
     bookTitle :: String 
    , bookAuthor :: String 
    , bookYear :: Int 
    , bookFans :: [String] 
    } deriving (Show,Read) 

接下來,如果你看看read類型:

> :t read 
read :: Read a => String -> a 

你可以看到它的返回類型是多態的。因此,爲了讓它正確解析,您需要讓GHC知道您希望解析的是什麼類型的類型。通常情況下,你可以使用分析得到的值,你通常會和GHC就能推斷出類型:

getFans = do 
    book <- readFile "book.txt" 
    return $ bookFans book 

但GHCI你必須給它一個暗示:

> let book = Book "the sound and the fury" "faulkner" 1929 ["me"] 
> show book 
"Book {bookTitle = \"the sound and the fury\", bookAuthor = \"faulkner\", bookYear = 1929, bookFans = [\"me\"]}" 
> read $ show book :: Book 
Book {bookTitle = "the sound and the fury", bookAuthor = "faulkner", bookYear = 1929, bookFans = ["me"]} 
+0

的問題已經在使用類型簽名'(讀取fileContent :: Database)',告訴編譯器它應該使用'Read'實例作爲'[Book]'。 – Cirdec 2015-03-02 15:29:42

+0

@Cirdec哦,當然。我錯過了。不知道爲什麼這保證了一個downvote雖然。我的回答是不正確的嗎?如果是的話,我很樂意學習我的錯誤。 :) – danem 2015-03-02 15:32:17

+0

你的回答完全正確,它只是不回答這個問題。作者已經爲'Book'擁有'Read'實例,或者無法編譯和運行'(read fileContent :: Database)'來獲得運行時錯誤'Prelude.read:no parse'。您添加到答案末尾的小ghci會話將演示「show」和「read」的含義。 show'可以是'Book's的標識,但並不能解釋爲什麼'books.txt'不能被讀取。 – Cirdec 2015-03-02 15:46:24