給定類X和Y,創建對方類實例的最習慣方法是什麼?例如 -非法實例聲明/重疊實例
instance (X a) => Y a where ...
instance (Y a) => X a where ...
我想避免擴展。此外,我知道這可能會導致一些令人討厭的無限遞歸,所以我打開一個完全不同的方法來完成相同的事情,並保持相對乾燥。下面給出了一些背景爲我有確切的問題 -
data Dealer = Dealer Hand
data Player = Player Hand Cash
class HasPoints a where
getPoints :: a -> Int
class (HasPoints a) => CardPlayer a where
getHand :: a -> Hand
viewHand :: a -> TurnIsComplete -> Hand
hasBlackjack :: a -> Bool
hasBlackjack player = getPoints player == 21 &&
(length . getCards . getHand) player == 2
busts :: a -> Bool
busts player = getPoints player > 21
我想做到這一點 -
instance (CardPlayer a) => HasPoints a where
getPoints = getPoints . getHand
但似乎我必須這樣做 -
instance HasPoints Dealer where
getPoints = getPoints . getHand
instance HasPoints Player where
getPoints = getPoints . getHand
編輯
似乎我最喜歡的方法是保持HasPoints
typeclass並執行CardPlayer
作爲data
。
data CardPlayer = Dealer Hand | Player Hand Cash
instance HasPoints CardPlayer where
getPoints = getPoints . getHand
getCash :: CardPlayer -> Maybe Cash
getHand :: CardPlayer -> Hand
viewHand :: CardPlayer -> TurnIsComplete -> Hand
hasBlackjack :: CardPlayer -> Bool
busts :: CardPlayer -> Bool
-- I wanted HasPoints to be polymorphic
-- so it could handle Card, Hand, and CardPlayer
instance HasPoints Hand where
getPoints Hand { getCards = [] } = 0
getPoints hand = if base > 21 && numAces > 0
then maximum $ filter (<=21) possibleScores
else base
where base = sum $ map getPoints $ getCards hand
numAces = length $ filter ((Ace==) . rank) $ getCards hand
possibleScores = map ((base-) . (*10)) [1..numAces]
instance HasPoints Card where
-- You get the point
但是你需要'HasPoints'作爲一個單獨的類嗎?你不能只刪除'HasPoints'並使'getPoints'成爲一個帶有'CardPlayer'約束的重載函數? – kosmikus 2013-04-23 07:54:18
類型類在這裏似乎沒有任何用處;我懷疑你應該從這個模塊中完全消除它們。爲什麼不只是'數據CardPlayer =經銷商手|玩家手牌現金「然後像'getHand(經銷商手)=手; getHand(玩家手現金)=手,然後'playerPoints = getPoints。 getHand'等等? – applicative 2013-04-23 13:39:38
@applicative - 我喜歡'數據CardPlayer =經銷商手|玩家手持現金「方法。但是,我想仍然使用HasPoints,所以getPoints函數可以是多態的。無論如何,你爲什麼不建議作爲回答而不是評論? – pyrospade 2013-04-27 05:45:24