在Haskell中使用`deriving`引发了什么?

Lan*_*ard 14 haskell

我刚刚开始学习Haskell.我已经看过许多介绍类型基础知识的介绍示例,但它们通常deriving在类型下面有一个声明.以下是RealWorldHaskell第3章的示例:

data Cartesian2D = Cartesian2D Double Double
                   deriving (Eq, Show)

data Polar2D = Polar2D Double Double
               deriving (Eq, Show)
Run Code Online (Sandbox Code Playgroud)

他们在第6章解释了一些,它可以帮助你了解它是如何被使用的.

到目前为止,我理解,deriving (Show)有必要告诉Haskell如何将您的类型转换为字符串.这在实际层面上是有道理的.我来自JavaScript的土地,所以对我来说,你很容易想象这将实现如下:

Polar2D.prototype.toString = function(){
  return '[Polar2D]';
};
Run Code Online (Sandbox Code Playgroud)

在Haskell中,他们给出了如何ShowColor类型实现自己的示例,而不是使用deriving.

data Color = Red | Green | Blue
instance Show Color where
  Red = "red"
  Green = "green"
  Blue = "blue"
Run Code Online (Sandbox Code Playgroud)

这意味着当你在ghcirepl中,你可以这样做:

> show Red
"red"
Run Code Online (Sandbox Code Playgroud)

但这并没有解释deriving实际上在做什么,这对我来说仍然是神奇的.

我的问题是,引擎盖下发生了deriving什么?另外,在Haskell源代码的GitHub上是否有一个地方可以看到实现?这也可能有所帮助.

Ste*_*ehl 16

GHC实际上只是编写您手工编写的相同实例,如果您传递-ddump-deriv给编译器,您可以看到它生成的代码.例如:

Prelude> data Color = Red | Green | Blue deriving (Show)

==================== Derived instances ====================
Derived instances:
  instance Show Color where
    showsPrec _ Red = showString "Red"
    showsPrec _ Green = showString "Green"
    showsPrec _ Blue = showString "Blue"
    showList = showList__ (showsPrec 0)


Generic representation:

  Generated datatypes for meta-information:

  Representation types:
Run Code Online (Sandbox Code Playgroud)

这里没有太大的魔力,Show只是有一个非常机械的实现.在里面它查看数据构造函数的内部形式(类型DataConRep在GHC的源中),它从翻译前端AST获得,然后查看前端源中提供的名称,并根据这些名称添加新的Show实例任何也实现Show的嵌套类型.新的自动生成的类型类注册就像手动编码的类一样,就好像它是在当前模块中编写的一样.