【发布时间】:2017-01-17 01:51:02
【问题描述】:
我正在尝试为 Exploding Kittens 的玩具实现生成套牌。
假设我有以下类型:
data ActionCard = Skip
| Attack
| Shuffle
| Nope
| Future
| Defuse
| Favor
deriving Enum
data BasicCard = TacoCat
| MommaCat
| Catermelon
| BearCat
| PotatoCat
| BikiniCat
| RainboRalphingCat
deriving Enum
data Card = ActionCard | BasicCard | BombCard
type Deck = [Card]
还有一个像这样的甲板生成器功能:
generateDeck :: Int -> Deck
generateDeck players = (concat (map (replicate 5) [TacoCat ..]))
++ (replicate 2 Nope)
++ (replicate 4 Skip)
++ (replicate 4 Attack)
++ (replicate 4 Shuffle)
++ (replicate 4 Future)
++ (replicate 1 Defuse)
++ (replicate 4 Favor)
++ (replicate (players + 1) BombCard)
这失败了:
Couldn't match expected type ‘[BasicCard]’
with actual type ‘a7 -> [a7]’
Probable cause: ‘replicate’ is applied to too few arguments
In the first argument of ‘(+)’, namely
‘replicate (length $ _players state)’
In the second argument of ‘(++)’, namely
‘(replicate (length $ _players state) + 1 BombCard)’
(以及其他非基本卡的类似错误)
这在某种程度上是有道理的,因为(concat (map (replicate 5) [TacoCat ..])) 返回一个[BasicCard],但是我希望函数签名强制使用更通用的类型?
如何允许Card 成为ActionCard、BasicCard 或BombCard?
【问题讨论】:
-
写
data Card = ActionCard | BasicCard | BombCard并不意味着Card将是Attack, ... ,RainboRalphingCat之一 - 而是创建三个 new 数据构造函数恰好与三个现有类型具有相同的名称。 -
可能是
data Card = Action ActionCard | Basic BasicCard | Bomb BombCard,那么您必须将[TacoCat ..]更改为map Basic [TacoCat..]并将Nope更改为(Action Nope)等等...
标签: haskell types algebraic-data-types