Reputation: 15481
I am attempting to generate a deck for a toy implementation of Exploding Kittens.
Say I had the following types:
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]
and a deck generator function like so:
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)
This fails with:
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)’
(and similiar errors for hte other non basic cards)
That makes sense on one level as (concat (map (replicate 5) [TacoCat ..]))
returns a [BasicCard]
, however I would have expected the function signature to force a more generic type?
How do allow for Card
to be either an ActionCard
, a BasicCard
, or a BombCard
?
Upvotes: 0
Views: 72
Reputation: 27656
data Card = ActionCard | BasicCard | BombCard
This creates a new datatype Card
with three constructors called ActionCard
, BasicCard
and BombCard
. This has nothing to do with the other two datatypes that are called ActionCard
or BasicCard
; the namespace of types and constructors is distinct.
What you want to do is to define Card
as either being an Action
comprising an ActionCard
, or a Basic
BasicCard
, or a BombCard
:
data Card = Action ActionCard | Basic BasicCard | BombCard
then you can make your Deck
by wrapping each card type in its correct constructor:
generateDeck :: Int -> Deck
generateDeck players = basics ++ actions ++ bombs
where
cats = concatMap (replicate 5 . Basic) [TacoCat ..]
actions = map Action . concat $
[ replicate 2 Nope
, replicate 4 Skip
, replicate 4 Attack
, replicate 4 Shuffle
, replicate 4 Future
, replicate 1 Defuse
, replicate 4 Favor
]
bombs = replicate (players + 1) BombCard
Upvotes: 4