2010-11-16 73 views
2

我是Haskell的新手,我正在寫一個簡單的AI決策系統來玩20個問題的遊戲風格。如果程序無法猜出正確的答案,它會要求提供一個問題來區分答案,並將該問題存儲在樹中。它在程序開始時從文件系統中讀取樹,並在最後將其寫回。調試Haskell閱讀功能

我在Haskell中的序列化代碼有很多問題。我收到錯誤「Prelude read:no parse」。這是怎麼回事?這裏是我的代碼:

import Data.Char 
import System.IO 

-- Defines a type for a binary tree that holds the questions and answers 
data Tree a = 
     Answer String | 
     Question String (Tree a) (Tree a) 
     deriving (Read, Show) 

-- Starts the game running 
main = do 
     let filePath = "data.txt" 
     fileContents <- readFile filePath 
     animals <- return (read fileContents) 
     putStrLn "Think of an animal. Hit Enter when you are ready. " 
     _ <- getLine 
     ask animals 
     writeFile filePath (show animals) 

-- Walks through the animals tree and ask the question at each node 
ask :: Tree a -> IO() 
ask (Question q yes no) = do 
     putStrLn q 
     answer <- getLine 
     if answer == "yes" then ask yes 
          else ask no 
ask (Answer a) = do 
     putStrLn $ "I know! Is your animal a " ++ a ++ "?" 
     answer <- getLine 
     if answer == "yes" then computerWins 
          else playerWins 

computerWins = do putStrLn "See? Humans should work, computers should think!" 

playerWins = do putStrLn "TODO" 

而且這裏是我使用的數據文件:

Question "Does it live in the water?" 
     ((Question "Does it hop?") (Answer "frog") (Answer "fish")) 
     (Answer "cow") 
+1

'Tree'不需要類型限定符 - 您可以輕鬆地用'Tree'替換所有'Tree a',而無需更改程序行爲。 – 2010-11-16 18:29:20

回答

4

read不打算可靠地處理之類的東西額外的括號。您的代碼適用於以下數據文件:

Question "Does it live in the water?" 
     (Question "Does it hop?" (Answer "frog") (Answer "fish")) 
     (Answer "cow") 
+0

令人驚歎的,謝謝! – stomcavage 2010-11-16 17:14:30

+4

@stomcavage:從長遠來看,使用[Parsec](http://hackage.haskell.org/package/parsec-3.0.1)來讀取數據文件可能會更好,因爲它會讓你更清晰錯誤消息,並允許在格式化方面有更多的變化(儘管我不確定你是否希望原始版本被認爲是有效的,因爲它表明構造器的'Question'只需要一個'String'參數)。 – 2010-11-16 17:17:49

+2

我只是想同意特拉維斯布朗,你真的很想用解析器。 Parsec很常見,但我更喜歡uu-parsinglib。 http://hackage.haskell.org/package/uu-parsinglib – 2010-11-16 17:23:30