我正在用 Haskell 写一个 ADT,它代表一手牌。我的问题是我想将(Suit,Face)
代表一张牌的数量限制为 5 代表一手牌。
data Card = Hand [(Suit,Face)]
我试图做的是这个,但它不起作用。
data Card = Hand [(Suit,Face),(Suit,Face),(Suit,Face),(Suit,Face),(Suit,Face)]
我的问题是:我如何将元组的数量限制为 5?
我正在用 Haskell 写一个 ADT,它代表一手牌。我的问题是我想将(Suit,Face)
代表一张牌的数量限制为 5 代表一手牌。
data Card = Hand [(Suit,Face)]
我试图做的是这个,但它不起作用。
data Card = Hand [(Suit,Face),(Suit,Face),(Suit,Face),(Suit,Face),(Suit,Face)]
我的问题是:我如何将元组的数量限制为 5?
我想补充一点,如果您使用基于 5 元组的解决方案(如其他答案中所建议的那样),您仍然可以拥有所需的所有折叠/遍历功能。特别是,首先定义
import Control.Applicative
import Data.Foldable
import Data.Traversable
data Tuple5 a = Tuple5 a a a a a
instance Traversable Tuple5 where
traverse f (Tuple5 a b c d e)
= Tuple5 <$> f a <*> f b <*> f c <*> f d <*> f e
instance Foldable Tuple5 where
foldMap = foldMapDefault
instance Functor Tuple5 where
fmap = fmapDefault
然后,您可以拥有
data Hand = Hand (Tuple5 Card)
Foldable
并使用/ Traversable
/中的任何方法折叠/遍历结构Functor
。
更新:最近我创建了一个小型库tuples-homogenous-h98,它定义newtype
了同质元组的别名,例如
newtype Tuple5 a = Tuple5 { untuple5 :: (a,a,a,a,a) }
并添加适当的Traversable
、Foldable
、Functor
和实例。Applicative
Monad
怎么样
data Card = Hand (Suit, Face) (Suit, Face) (Suit, Face) (Suit, Face) (Suit, Face)
?
或者,如果你真的想使用列表(我的意思是,如果你想要 15 张牌,我的建议会变得非常愚蠢),你可以保留data Card = Hand [(Suit, Face)]
然后告诉用户不要使用构造函数,而是提供一个“智能构造函数”像
fromList :: [(Suit, Face]) -> Maybe Card
fromList xs
| length xs == 5 = Just (Hand xs)
| otherwise = Nothing
然后,您还可以让构造函数本身可用,并发出警告,例如“仅在您保证提供的列表包含正好 5 个元素时使用”。
顺便说一句:命名数据类型Card
和构造函数是不是Hand
有点违反直觉?我认为应该Hand
在您的情况下调用数据类型。Card
是一个很好的别名Suit
-Face
对,所以你可以做type Card = (Suit, Face)
and data Hand = Hand [Card]
。
您可以为 Cards 和 Hand 类型创建一个包含五个 Card 元素的类型:
type Card = (Suit, Face)
data Hand = Hand Card Card Card Card Card