这是一个有点取巧的解决方案,需要打些额外的字,但不需要使用反引号!我最初是在 Reddit 上发布的,如果可以的话。
我假设你已经为 Rank 派生了 Enum。
data OF = OF
ace :: OF -> Suit -> PokerCard
ace _ s = PokerCard Ace s
-- or point-free
two :: OF -> Suit -> PokerCard
two _ = PokerCard Two
-- or with const
three :: OF -> Suit -> PokerCard
three = const (PokerCard Three)
-- you get the idea!
-- the rest in one line:
four,five,six,seven,eight,nine,ten,jack,king :: OF -> Suit -> PokerCard
[four,five,six,seven,eight,nine,ten,jack,king] = map (const . PokerCard) [Four .. King]
-- now you can write
pokerDeck = [
ace OF Spades, two OF Spades -- and so on
]
OF数据类型并非必需,但可以避免出现令人困惑(但非常技术)的内容,例如
ace "Motorhead" Spades
。您仍然可以编写
ace undefined Spades
,我认为这真的没有办法避免。
如果
of
不是一个关键字,您甚至可以编写
of = OF
。
还有一种极其恶劣的黑客方式来完全摆脱'of'这个词,使用数字代替卡片:
{-# LANGUAGE FlexibleInstances #-}
instance Num (Rank -> Suit) where
fromInteger n = (undefined : map Card[Ace .. King]) !! (fromInteger n)
现在,2 Spades :: Card
类型检查通过(但您需要显式类型!)并且它就是您想要的 :-) 但是,我强烈建议您不要在正式的代码中这样做;但它看起来很酷。