繁体   English   中英

Haskell继承类型类

[英]Haskell inheriting type classes

假设我有以下课程:

class P a where
  nameOf :: a -> String

我想声明此类的所有实例都是Show实例。 我的第一次尝试是:

instance P a => Show a where
  show = nameOf

昨天我第一次尝试使用这种方式导致了语言扩展的混乱:首先被告知要打开灵活的实例,然后打开不确定的实例,然后再打开实例,最后遇到关于重复实例声明的错误。 我放弃并返回重复代码。 但是,从根本上讲,这似乎是一个非常简单的需求,应该容易满足。

因此,有两个问题:

  1. 有没有一种我刚才错过的简单方法?
  2. 为什么会出现重叠实例问题? 我可以看到为什么我可能需要UndecidableInstances ,因为我似乎违反了Paterson条件,但是这里没有重叠的实例:甚至没有P实例。 为什么类型检查器认为Show Double有多个实例(在这个玩具示例中似乎就是这种情况)?

之所以会出现重叠实例错误,是因为您的P某些实例可能具有Show其他实例,然后编译器将无法决定使用哪个实例。 如果您有一个DoubleP实例,那么您将获得Show for Double两个实例:您的常规实例和已经在Haskell基库中声明的实例。 @augustss在您的问题注释中正确说明了如何触发此错误。 有关更多信息,请参见规格

如您所知,没有UndecidableInstances ,就无法实现您正在尝试的东西。 启用该标志时,您必须了解您正在承担编译器的责任,以确保不会出现任何冲突的实例。 这意味着,当然,您的库中不得存在其他任何Show实例。 这也意味着您的库不会导出P类,这将消除库用户声明冲突实例的可能性。

如果您的情况与上述内容有冲突,则可以肯定地表明问题一定存在。 实际上有...


首先,您要实现的目标是错误的。 您缺少有关Show类型类的几点要点,将其与流行的OO语言的toString方法之类的构造区分开来:

  1. 秀的黑线码头

    show的结果是在语法上正确的Haskell表达式,其中仅包含常量,并且在声明类型的那一刻使用了固定性声明。 它仅包含在数据类型,括号和空格中定义的构造函数名称。 当使用带标签的构造函数字段时,还使用大括号,逗号,字段名称和等号。

    换句话说,声明Show实例并不会产生有效的Haskell表达式本身是错误的。

  2. 鉴于上述情况,当类型允许简单地派生Show时,声明Show的自定义实例就没有意义。

  3. 当某个类型不允许派生它时(例如GADT),通常您仍然必须坚持使用特定于类型的实例来产生正确的结果。

因此,如果您需要自定义表示功能,则不应为此使用Show 只需声明一个自定义类,例如:

class Repr a where
  repr :: a -> String

并负责任地处理实例声明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM