我有代码:
data Value = A|Two|Three...Ten|J|Q|K deriving (Eq, Ord, Enum)
instance Show Value where
show A = "A"
show Two = "2"
....
show K = "K"
另一个数据Suite
具有类似的Show
实例,用于Hearts
、Spades
、Clubs
和Diamonds
。
如果我有
type Card = (Value, Suite)
是否可以创建一个将(A, Spades)
转换为字符串"AS"
的 show 函数?
您应该为Card
定义一个newtype
(或data
类型(,为其编写Show
实例。
newtype Card = Card (Value,Suite)
instance Show Card where
show (Card (v,s)) = show v ++ show s
您还可以启用TypeSynonymInstances
并在编写实例时为 Card
编写实例。
编辑:我可能还应该提到,类型同义词不是处理您的情况的惯用/哈斯克尔式方式。Card
在语义上不同于一对Value
和Suite
,它可以表示(例如(纸牌游戏中的某个初始条件,而不一定是实际的卡牌。
应该定义自己的数据类型,而不是使用 (,)
。
data Card = Card Value Suite
instance Show Card where
show (Card v s) = show v ++ show s
要定义type
的实例,您需要使用 TypeSynonymInstances
扩展。在您的情况下instace Show Card
等同于instance Show (Card, Suite)
。如果没有FlexibleInstance
,这是不允许的,因为标准类型类只允许 Show (a,b)
等内容的实例。
现在,使用 FlexibleInstance
是不够的,因为Show (a,b)
已经定义,并且您的新实例将与默认实例重叠。
编译器如何在您的 Show (Card, Value)
实例和标准实例之间进行选择Show (a,b)
?(使用类型是不够的,因为类型就像执行文本替换一样。
要解决实例重叠的问题,您需要使用 OverlappingInstance
扩展。这有点棘手,通常不建议使用。