如何定义超类?

bim*_*mmo 4 haskell class instance

如何在Haskell中定义超类?我的情况是我已经定义了一个类StringHashed,它将成员的名称映射为String.我希望实现,连接质量,所有tShow t通过将字符串名称简单地返回show t.我是否正确地说StringHashed现在是Show的超类?以下是我想写的内容:

class StringHashed t where
    stringHash :: t -> String

instance Show t => StringHashed t where
    stringHash = show
Run Code Online (Sandbox Code Playgroud)

但是Haskell抱怨无效的实例声明.我也尝试过instance StringHashed (Show t)其他语法运球; 没有人对我有用.我还阅读了关于GHC wiki的提议,但没有提供任何解决方案.这是一个.我担心使用-XFlexibleInstances只是因为它不是默认的.有没有一种正确的方法来实现一般的实例声明?或者我对Haskell的类型系统要求太高了?

Ørj*_*sen 10

事后不能添加Haskell超类 - 需要在子类的声明中提及它们.定义像你在问题中所做的实例,虽然可能有扩展,但可能会产生细微的重叠问题.

FlexibleInstances本身不是问题 - 它是GHC最无害的扩展之一.问题是GHC的实例查找方法意味着

instance Show t => StringHashed t where ...
Run Code Online (Sandbox Code Playgroud)

将此实例定义为适用于所有类型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
Run Code Online (Sandbox Code Playgroud)

这允许您为仅适用于某些实例类型的方法编写默认值.但请注意,您仍需要为每种类型编写实际的实例声明 - 但它的主体可以为空.