haskell - 接口(interface)抽象设计

标签 haskell abstraction monads typeclass monad-transformers

目前,我尝试编写一个小游戏程序(Skat)作为一个爱好项目。 Skat 是一个花样游戏,两个玩家对抗一个玩家。由于有不同种类的播放器(本地播放器、网络播放器、计算机等),我想抽象出播放器的接口(interface)。

我的基本想法是使用类型类 Player ,它定义了所有类型的事情,一个玩家必须做和知道的(打牌,得到通知谁赢了把戏,等等)。然后,整个游戏就由一个函数 playSkat :: (Player a, Player b, Player c) => a -> b -> c -> IO () 完成。在哪里 a , bc可能是不同类型的玩家。然后玩家可能会以实现定义的方式使用react。本地玩家会在他的终端上收到一些消息,网络玩家可能会通过网络发送一些信息,而计算机玩家可能会计算新策略。

因为玩家可能想要做一些 IO 并且肯定想要有某种状态来跟踪私有(private)事物,所以它必须生活在某种 Monad 中。所以我想定义Player像这样的类:

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

这种模式似乎与状态转换器非常相似,但我不知道如何处理它。如果我把它写成 IO 之上的一个额外的 monad-transformer,那么一天结束时我就有了三个不同的 monad。我怎样才能以一种好的方式编写这个抽象?

为了澄清,我需要的是,通常的控制流应该是这样的:
玩诡计时,第一个玩家出牌,然后是第二个,最后是第三个。为此,逻辑需要执行函数playCard每个玩家的三次。之后,逻辑决定哪位玩家获胜,并将获胜者的信息发送给所有玩家。

最佳答案

首先,请记住类型类的主要目的是允许函数重载,即您可以在不同类型中使用单个函数。您实际上并不需要,因此最好使用类似以下的记录类型

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

其次,有些玩家需要 IO 而有些不需要的问题可以通过自定义 monad 来解决。我写了相应的example code玩井字游戏,这是我的 operational 的一部分包裹。

关于haskell - 接口(interface)抽象设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5769726/

相关文章:

domain-driven-design - 所有 "bulk"操作都属于 DDD 的什么地方?

java - 我如何限制我的客户使用类里面选定的方法?

haskell - 什么是单子(monad)类别的仿函数?

list - 在 Haskell 中的元组列表中累积值计数

database - 在保持抽象的同时将格式化文本存储在数据库中

haskell - 带 fclabel 的 STM

haskell - 一个函数中的两个多态类

haskell - 为什么 "return Nothing"什么都不返回?

haskell - 有 "parse error on input ‘->’ "的情况下

algorithm - 如何在 Haskell 中标记树中的节点?