2017-02-01 4 views
1

私はクイズアニマルゲームを書くタスクがあります。私はファイルから木のデータを読む必要があります(ファイルの構造は自由です)。ゲームの終了後、新しいデータをツリーに追加することができます(実際には(動物))(Node(Animal)(動物)によって置換されます。ハスケルのファイルからバイナリツリーを解析する

私の問題は、 "データベース"の内容を解析できないことです。 TXT」AnimalsTreeで

例 "database.txt"(このコンテンツは、呼び出し '新しいゲーム' の前に書面で生成される):

module Main where 
import System.IO 
data AnimalsTree = Animal String | Question String AnimalsTree AnimalsTree deriving (Read, Show) 
-- Видовете отговори на потребителя 
data Answer = Yes | No 

main :: IO() 
main = do root <- "database.txt" 
      play (read root) 
      return() 

play :: AnimalsTree -> IO AnimalsTree 
play root = do putStrLn "Think of an animal, I will try to guess what it is..." 
       newRoot <- play' root 
       writeFile "database.txt" (show newRoot) 
       playAgain <- ask "Do you want to play again?" 
       case playAgain of 
        Yes -> play newRoot 
        No -> do putStrLn "Bye!" 
          return newRoot 

play' :: AnimalsTree -> IO AnimalsTree 
play' [email protected](Question q l r) = do ans <- ask q 
            case ans of 
             Yes -> do y <- play' l 
                return $ Question q y r 
             No -> do n <- play' r 
                return $ Question q l n 

play' [email protected](Animal _) = do ans <- ask $ "Are you thinking of " ++ show' animal ++ "?" 
          case ans of 
           Yes -> do putStrLn "I win! :)" 
              return animal 
           No -> do putStrLn "I give up, you win!" 
              getNewAnimal animal 


getNewAnimal :: AnimalsTree -> IO AnimalsTree 
getNewAnimal animal = do putStrLn "Please help me!" 
         putStrLn "What is name of yout animal?" 
         name <- getLine 
         let newAnimal = Animal name 
         putStrLn $ "Now please enter a question that answers yes for " ++ show' newAnimal ++ " and no for " ++ show' animal 
         question <- getLine 
         return $ Question question newAnimal animal 

ask :: String -> IO Answer 
ask s = do putStrLn $ s ++ " (Yes/No)" 
      getAnswer 

getAnswer :: IO Answer 
getAnswer = do ans <- getLine 
       putStrLn "" 
       case ans of 
        "y" -> return Yes 
        "Y" -> return Yes 
        "yes" -> return Yes 
        "Yes" -> return Yes 
        "n" -> return No 
        "N" -> return No 
        "no" -> return No 
        "No" -> return No 
        _ -> putStrLn "This is incorect answer! Please try again with value in 'Yes' or 'No'!" >> getAnswer 

show' (Animal name) = (if elem (head name) "AEIOUaeiou" then "an " else "a ") ++ name 
show' (Question q _ _) = q 

Question "Is it fly?" (Animal "Bird") (Question "Is it swim?" (Animal "Fish") (Animal "Dog"))

EDIT これは完全なコードですしかし、私はエラーを取得、次の

は:

test3.hs:10:19: 
    No instance for (Read (IO AnimalsTree)) 
     arising from a use of ‘read’ 
    In a stmt of a 'do' block: root <- read "database.txt" 
    In the expression: 
     do { root <- read "database.txt"; 
      play (root); 
      return() } 
    In an equation for ‘main’: 
     main 
      = do { root <- read "database.txt"; 
       play (root); 
       return() } 
+5

あなたはすでに 'Read'を導いています。それはあなたに無料のパーサを与えませんか?あるいは、何をしようとしましたか、何が起こると予想されましたか、代わりに何が起こったのですか? –

+0

私の投稿を編集する! –

+0

'main'関数から純粋な値を返すことはできません。また、 'return'はCやJavaのような言語からの' return'ではなく、非常に強力な抽象化ツールである 'Monad'という型クラスの関数です。 – ThreeFx

答えて

2

これは素晴らしいスタートのように見えます!私はそれをコンパイルするために得るためにあなたのmain機能にreadFileを追加する必要:

main = do root <- readFile "database.txt" 

あなたがreadFileから切り替える必要があり、明示的に、読書のためのファイルを開く読書をしていて、ファイルをクローズすることは可能です。これは、readFileがファイルをいつ閉じるかを保証していないためで、writeFileはすでに開いているファイルへのパスが与えられていれば失敗することができるからです。

あなたはこれを行う方法の詳細についてopenFilehGetLine、およびhCloseのマニュアルを読んで(しかしそれがないreadFile同じ警告を持っているとして、hGetContentsを注意してください)することができます。

+0

あなたは英雄です!ありがとうございました!私の人生を救うだけ! ^。^ –

関連する問題