给定类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