2010-11-16 135 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