如何定义超类



如何在Haskell中定义超类?我的情况是,我定义了一个类StringHashed,它将成员映射到他们的名称作为String。我希望通过使字符串名称简单地返回show t来实现Show t中的所有t。我说StringHashed现在是Show的一个超类,对吗?以下是我想写的内容:

class StringHashed t where
    stringHash :: t -> String
instance Show t => StringHashed t where
    stringHash = show

但是Haskell抱怨一个无效的实例声明。我也尝试过instance StringHashed (Show t)和其他句法运球;没有一个对我有效。我也在GHC维基上读到一个没有提供解决方案的提案。就是这个。我担心使用-XFlexibleInstances,因为它不是默认的。是否有适当的方法来实现一般实例声明?还是我对Haskell的类型系统要求太高了?

Haskell超类不能添加在事实之后——它们需要在子类的声明中提及。像你在问题中所做的那样定义一个实例,虽然可以使用扩展,但可能会产生微妙的重叠问题。

FlexibleInstances本身并不是问题所在,它是GHC最无害的扩展之一。问题是GHC的实例查找方法意味着

instance Show t => StringHashed t where ...

将此实例定义为适用于所有类型t-Show t限制只是在查找后检查的事后考虑。因此,它将与您可以创建的所有其他实例重叠,虽然有一个扩展OverlappingInstances允许这样做,但它的使用被认为有些可疑。

然而,GHC有一个功能DefaultSignatures,它是为类似于您的用例设计的:

{-# LANGUAGE DefaultSignatures #-}
class StringHashed t where
    stringHash :: t -> String
    default stringHash :: Show t => t -> String
    stringHash = show
instance StringHashed Int

这允许您为只适用于某些实例类型的方法编写默认值。但是,请注意,您仍然需要为每个类型编写一个实际的实例声明,但其主体可以是空的。

最新更新