Haskell: моделирование состояний онлайн-игр для графического интерфейса пользователя

Я пишу клиентский интерфейс для онлайн-игры. Он структурирован как модуль Model , который представляет состояние игры, и модуль View , который отслеживает текущее состояние игры и обновляет его, используя переходы модели, т.е. функции из одного состояния в еще один. Чтобы воспользоваться преимуществами статической проверки типов, я смоделировал состояния как отдельные типы с классами типов, представляющими общие черты:

class Erring s where errors :: s -> [String]
class WithPlayers s where players :: s -> [String]
class Erring s => LoggedIn s

data LoggedOut = LoggedOut [String] deriving (Eq, Show)
instance Erring LoggedOut where errors (LoggedOut es) = es

data Ready = Ready [String] [String] deriving (Eq, Show)
instance Erring Ready where errors (Ready _ es) = es
instance LoggedIn Ready
instance WithPlayers Ready where players (Ready ps _) = ps

data NotReady = NotReady [String] [String] deriving (Eq, Show)
instance Erring NotReady where errors (NotReady _ es) = es
instance LoggedIn NotReady
instance WithPlayers NotReady where players (NotReady ps _) = ps

-- some transitions:

login :: String -> LoggedOut -> Either Ready LoggedOut
login pwd (LoggedOut es) = 
  if pwd == "password" then Left $ Ready [] es
  else Right $ LoggedOut (es ++ ["incorrect password"])

logout :: LoggedIn s => s -> LoggedOut
logout s = LoggedOut $ errors s

Это может быть немного утомительным, когда есть десятки состояний и экземпляров, которые нужно определить, но в результате получается надежный API.

Войдите в просмотр. Для хранения состояния я хотел использовать TMVar , чтобы и поток пользовательского интерфейса, и поток обработки сообщений от сервера могли выполнять переходы между состояниями. Поскольку каждое состояние относится к разному типу, я создал новый тип, который может представлять все возможные состояния:

data SessionState = SSLoggedOut LoggedOut
                  | SSReady Ready
                  | SSNotReady NotReady

Теперь можно определить ссылку на состояние типа TMVar SessionState .

Теперь это кажется не совсем правильным. По сути, мне приходится определять каждое состояние дважды, один раз как тип, а второй раз как конструктор типа, обертывающий этот тип. Итак, вопросы:

  1. Разумно ли моделировать состояние игры таким образом?
  2. Разумно ли сохранять значение состояния в TMVar , если атомарные обновления разными потоками являются обязательными или есть ли лучший способ отслеживать состояние?
  3. Если TMVar правильный путь, тогда необходимо ли определять что-то вроде SessionState оболочки?
5
задан narthi 14 March 2011 в 00:16
поделиться