Ahm*_*d B 3 haskell typeclass type-families
作为某种形式的实验,我试图为 Haskell 中的纸牌游戏定义一个非常通用的逻辑。为了保证最大的抽象级别,我定义了以下类型类:
class (Monad m) => CardGame m where
data Deck m :: *
data Card m :: *
data Player m :: *
game :: m () -- a description of the game's rules
draw :: Deck m -> m (Card m) -- top card of deck is drawn
pick :: Deck m -> Player m -> m (Card m) -- player selects card from a deck
-- so on and so forth
Run Code Online (Sandbox Code Playgroud)
这门课对我来说非常令人满意,因为它保留了将使用哪些卡(例如塔罗牌、法国花、德国花等)、玩家是谁等以及游戏应该运行什么样的底层单子的问题进入。
现在假设我想定义类似战争的纸牌游戏。这些游戏是在两个玩家之间进行的,每个玩家收到一副法式纸牌游戏,但是游戏本身有很多变体,所以我无法提前指定确切的规则是什么(即game) 我怎样才能部分特化上面的类型类?编译器对以下情况感到不安:
data Suit = Heart | Diamond | Spade | Club
data Value = Number Int | Jack | Queen | King
data FrenchSuited = Card Suit Value
class (Game m) => War m where
-- syntax error in the following line:
data Card m = FrenchSuited -- any War-like game must be played on French-suited card
deck1 :: Deck m
deck2 :: Deck m
player1 :: Player m
player2 :: Player m
Run Code Online (Sandbox Code Playgroud)
你看到我可以做到这一点的方法吗?
PS:战争类游戏真的可以用任何类型的卡玩,但这只是一个例子。我对如何实现我所追求的类型类的部分专业化类型更感兴趣。
你不能用数据族来做到这一点:Card m必须是一个不同的类型,Card m'用于不同的m和m'。这是因为数据族需要是单射的,就像常规类型构造函数一样。
充其量,Card m并且Card m'可以与 同构FrenchSuited。
相反,类型族没有这种注入性限制,但正因为如此,它们有时会使类型检查更加微妙,需要用户以某种方式解决一些歧义。话虽如此,您可以按如下方式要求您的类型:
{-# LANGUAGE TypeFamilies, AllowAmbiguousTypes #-}
class (Monad m) => CardGame m where
type Deck m :: *
type Card m :: *
type Player m :: *
game :: m () -- a description of the game's rules
draw :: Deck m -> m (Card m) -- top card of deck is drawn
pick :: Deck m -> Player m -> m (Card m) -- player selects card from a deck
-- so on and so forth
data Suit = Heart | Diamond | Spade | Club
data Value = Number Int | Jack | Queen | King
data FrenchSuited = Card Suit Value
class (CardGame m, Card m ~ FrenchSuited) => War m where
deck1 :: Deck m
deck2 :: Deck m
player1 :: Player m
player2 :: Player m
Run Code Online (Sandbox Code Playgroud)
该Card m ~ FrenchSuited子类中的约束力量型的平等。
| 归档时间: |
|
| 查看次数: |
71 次 |
| 最近记录: |