是否可以为类型别名声明类型类实例



我有代码:

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实例,用于HeartsSpadesClubsDiamonds

如果我有

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在语义上不同于一对ValueSuite,它可以表示(例如(纸牌游戏中的某个初始条件,而不一定是实际的卡牌。

您可能

应该定义自己的数据类型,而不是使用 (,)

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 扩展。这有点棘手,通常不建议使用。

最新更新