2016-09-09 71 views
0

我正試圖爲爆炸小貓的玩具實現生成一個套牌。由多種其他數據類型之一選擇表示的數據類型

說我有以下幾種類型:

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)’ 

(和similiar錯誤的興田其他非基本卡)

這在一個層次上有意義,因爲(concat (map (replicate 5) [TacoCat ..]))返回一個[BasicCard],但是我會期望函數簽名強制更通用的類型?

Card如何允許爲ActionCardBasicCardBombCard

+1

寫'數據卡= ActionCard | BasicCard | BombCard'並不意味着'Card'將成爲'Attack',...,'RainboRalphingCat'中的一個 - 而是它會創建三個碰巧與三個現有類型名稱相同的_new_數據構造函數。 – Alec

+2

可能是數據卡= Action ActionCard | Basic BasicCard |炸彈BombCard「,那麼你將不得不將'[TacoCat ..]'改成'將Basic [TacoCat ..]和'Nope'映射到'(Action Nope)',等等...... – Alec

回答

4
data Card = ActionCard | BasicCard | BombCard 

這將創建一個新的數據類型Card有三個構造稱爲ActionCardBasicCardBombCard。這與另外兩個數據類型無關,即ActionCardBasicCard;類型和構造函數的命名空間是不同的。

你想要做的就是定義Card因爲無論是作爲一個Action包括ActionCardBasicBasicCardBombCard

data Card = Action ActionCard | Basic BasicCard | BombCard 

那麼你可以讓你的Deck通過包裝每張卡類型其正確的構造函數:

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