クラス X と Y が与えられた場合、互いのクラスのインスタンスを作成するための最も慣用的なアプローチは何ですか? 例 -
instance (X a) => Y a where ...
instance (Y a) => X a where ...
延長は避けたいです。また、これにより厄介な無限再帰が発生する可能性があることを認識しているため、同じことを達成し、比較的 DRY を維持するためのまったく異なるアプローチを受け入れます。以下に、私が抱えている正確な問題に関するいくつかのコンテキストを示します-
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
実装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