首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell游戏中将抽象数据类型保存并加载到json文件和读取文件中

Haskell游戏中将抽象数据类型保存并加载到json文件和读取文件中
EN

Stack Overflow用户
提问于 2019-10-17 23:46:11
回答 1查看 222关注 0票数 0

我正在用Haskell编写一个游戏,其中我想将一个抽象数据类型的列表保存到一个JSON格式的文本文件中,然后重新加载保存的文件。也就是说,将该文件读入抽象数据类型的列表中,然后在我的游戏中正常使用该重新加载的列表。总的来说,我对Haskell和编程非常陌生,所以我有点不确定这在一开始是否可行。

我相信我正确地设置了我的数据类型(房间)。但是我不确定FromJson和toJSON (语法正确吗?)。

此外,我目前保存的方式并不是以我想要的格式保存JSON文件:

{“奖励”:“宝藏”,“敌人”:“enemyOne”,“描述”:“这是一个房间”}

而描述、敌人和奖赏应该是命令。

(我还认为data应该放在JSON文件的所有内容之前,对吗?)

如果你需要更多的澄清,请告诉我。谢谢!

代码语言:javascript
复制
{-# LANGUAGE 
    OverloadedStrings
  , DeriveGeneric
 #-}

module Game where

--import System.IO
import Text.Read
import Data.Char
import Prelude hiding (readFile, writeFile)

import Data.Aeson
import Data.Text as T hiding (length, tail)
import Data.ByteString.Lazy as B hiding (putStrLn, length, tail, writeFile, readFile)
import Data.ByteString.Lazy.Char8 as BC hiding (putStrLn, length, tail)
import GHC.Generics


data Room = Room
   { description :: String
   , enemy :: String
   , reward :: String
   } deriving (Show, Generic)

-- is this syntax correct for parseJSON?
instance FromJSON Room where
   parseJSON (Object v) =  Room <$> v .: "description" <*> v .: "enemy" <*> v .: "reward" 

-- is this syntax correct for toJSON? 
instance ToJSON Room where
    toJSON (Room desc enem reward) = object ["description" .= desc, "enemy" .= enem, "reward" .= reward]



save lst =
    do
    writeFile "savegame.txt" (encode lst)
    return()

load =
   do
   lst <- readFile "savegame.txt"
   let new = decode lst
   start new 

start :: [Room] -> IO()
start lst =
 putStrLn("Starting the game, need to use the lst as a list of rooms")

下面是我收到的错误消息:

代码语言:javascript
复制
forStackOverflow.hs:46:14:
    No instance for (FromJSON a0) arising from a use of ‘decode’
    The type variable ‘a0’ is ambiguous
    Relevant bindings include
      new :: Maybe a0 (bound at forStackOverflow.hs:46:8)
    Note: there are several potential instances:
      instance FromJSON DotNetTime
        -- Defined in ‘aeson-1.4.5.0:Data.Aeson.Types.FromJSON’
      instance FromJSON Value
        -- Defined in ‘aeson-1.4.5.0:Data.Aeson.Types.FromJSON’
      instance FromJSON a => FromJSON (Control.Applicative.Const a b)
        -- Defined in ‘aeson-1.4.5.0:Data.Aeson.Types.FromJSON’
      ...plus 89 others
    In the expression: decode lst
    In an equation for ‘new’: new = decode lst
    In the expression:
      do { lst <- readFile "savegame.txt";
           let new = decode lst;
           start new }

forStackOverflow.hs:47:10:
    Couldn't match expected type ‘[Room]’ with actual type ‘Maybe a0’
    Relevant bindings include
      new :: Maybe a0 (bound at forStackOverflow.hs:46:8)
    In the first argument of ‘start’, namely ‘new’
    In a stmt of a 'do' block: start new
Failed, modules loaded: none.
Prelude> 
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-18 01:12:17

来自Data.Aeson的函数Data.Aeson(从其文件中可以清楚地看到)返回的不是目标类型(无论您试图解码哪种类型),而是包装在Maybe中的目标类型。在您的例子中,这将是Maybe [Room],而不仅仅是[Room]

这反映了一个事实,即解码可能失败(即格式不正确或其他什么),在这种情况下,函数返回Nothing

当编译器说“相关绑定包括:新的::可能的a0”时,编译器就是这样告诉您的--它说变量new被推断为具有Maybe a0类型,其中a0是一些尚未知道的类型。

然后,它又告诉您,它不能将Maybe a0作为参数传递给start,因为start需要[Room]类型的参数:“无法将预期类型的start与实际类型‘可能a0’相匹配.在‘开始’的第一个参数中

要解决这个问题,您需要处理decode返回Nothing的可能性,如果它返回Just,则将其内容传递给start。就像这样:

代码语言:javascript
复制
load =
   do
   lst <- readFile "savegame.txt"
   let new = decode lst
   case new of
      Nothing -> 
         error "Incorrect file format"
      Just n ->
         start n

(请注意,调用error不是处理意外情况的好方法;我只将其用作示例)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58442109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档