接口抽象的设计 [英] Design of interface abstraction

查看:188
本文介绍了接口抽象的设计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前,我尝试编写一个小型游戏程序(Skat)作为一个爱好项目。斯卡特是一个诡计多端的比赛,两名球员对阵一名球员。由于有不同类型的玩家(lokal玩家,网络玩家,电脑等),我想将界面抽象到玩家。

我的基本想法是使用一个类型类型 Player ,它定义了玩家必须做的所有事情并且知道(打牌,获得关于谁赢得比赛的通知等)。然后,整个游戏仅由 playSkat ::(Player a,Player b,Player c)=> a - > b - > c - > IO()其中 a b c 可能是不同种类的玩家。玩家可能会以实现定义的方式做出反应。一位卡拉OK玩家会在他的终端上看到一些信息,网络玩家可能会通过网络发送一些信息,而电脑玩家可能会计算出一个新的策略。因为玩家可能会想要做一些IO并明确想要有某种状态来追踪私人事物,它必须生活在某种Monad中。所以我想过如下定义 Player 类:

  class Player p其中
playCard :: [Card] - > p - > IO(Card,p)
notifyFoo :: Event - > p - > IO p
...

这种模式看起来与状态转换器非常相似,但我不知道如何处理它。如果我将它写成IO之外的额外单变换器,那么在一天结束时我会有三个不同的monad。为了澄清,我需要的是,通常的控制流程应该如何:

b当玩牌时,第一个玩家玩牌,然后第二个,最后是第三个玩家。为此,逻辑需要为每个玩家执行函数 playCard trice。之后,逻辑决定哪个玩家获胜,并将赢得的信息发送给所有玩家。解决方案

首先,请记住类型类的主要目的是允许重载函数,也就是说,您可以使用不同类型的单个函数。你并不需要这么做,所以你最好用类型为记录的类型。

  data Player = Player { playCard :: [Card]  - > IO(Card,Player),...} 





其次,一些玩家需要IO而有些玩家不能解决的问题可以用一个自定义monad来解决。我为TicTacToe游戏编写了相应的示例代码,这是我的运营包。


Currently, I try to write a small game program (Skat) as a hobby project. Skat is a trick-taking game were two players play against a single player. As there are different kinds of players (lokal player, network player, computer, etc.), I wanted to abstract the interface to the player.

My basic idea is to use a typeclass Player, that defines all kind of things, a player have to do and to know (playing a card, get notified about who won the trick, etc). Then, the whole game is just done by a function playSkat :: (Player a, Player b, Player c) => a -> b -> c -> IO () where a, b and c might be different kinds of players. A player might then react in a implementation defined way. A lokal player would get some message on his terminal, a network player might send some information over the network and a computer player might calculate a new strategy.

Because the player might want to do some IO and definitly want to have some kind of state to track private things, it has to live in some kind of Monad. So I thought about defining the Player class like this:

class Player p where
  playCard :: [Card] -> p -> IO (Card,p)
  notifyFoo :: Event -> p -> IO p
  ...

This pattern seems to be quite similar to a state transformer, but I am not shure how to handle it. If I would write it as an extra monad-transformer on top of IO, I had three different monads at the end of the day. How can I write this abstraction in a good way?

To clarify, what I need, here is how a usual control flow should look like:
When playing a trick, the first player plays a card, then the second, and finally the third. To do this, the logic needs to execute the function playCard trice for each player. Afterwards, the logic decides, which player wins the trick and sends the information who won to all players.

解决方案

First of all, keep in mind that the main purpose of type classes is to permit overloading of functions, i.e. that you can use a single function at different types. You don't really require that, so you are better off with a record type along the lines of

data Player = Player { playCard :: [Card] -> IO (Card, Player), ... }


Second, the problem of some players needing IO and some not can be solved with a custom monad. I have written corresponding example code for a game of TicTacToe, which is part of my operational package.

这篇关于接口抽象的设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆