在计算机科学中，**类型类**（type class），是支持特设多态的类型系统构造。这是通过向参数多态类型的类型变量增加约束完成的。这种约束典型的涉及到一个类型类`T`和一个类型变量（英语：）`a`，并意味着`a`所能实例化的类型，其成员必须支持关联于`T`的重载运算。

类型类首先在Haskell中实现，当时Philip Wadler和Stephen Blott提出它，作为对Standard ML的`eqtype`的扩展，并且最初构想为以本原方式实现重载算术及等式算符的一种途径。
对比于Standard ML的"eqtypes"，在Haskell中通过使用类型类重载等式算符，不要求编译器前端或底层类型系统的广泛修改。

自从它们创立之后，已经发现了类型类的很多其他应用。

概述
--

定义类型类需要通过规定一组函数或约束名字，它们分别具有同在的类型，它们对属于这个类的所有类型都必须存在。在Haskell中，类型可以被参数化，意图包含允许等式的类型一个类型类`Eq`，可以如下这样声明：

```
class Eq a where
 (==) :: a -> a -> Bool
 (/=) :: a -> a -> Bool
 x /= y = not (x == y)
 x == y = not (x /= y)

```

这里的`a`是类型类`Eq`的一个实例，并且`a`定义的函数签名，针对了2个函数（等式和不等式函数），它们每个都接受2个类型`a`的实际参数并返回一个布尔值。这个声明可以读作："类型`a`属于类型类`Eq`，如果在其上定义了有适当类型的，叫做`(==)`、`(/=)`的的函数。"

编程者可以使任何类型`t`成为给定类型类`C` 的成员，通过使用"实例声明" 为特定类型`t`实现所有的`C`方法。如果编程者定义一个新的记录数据类型`Foo`，可以接着使这个新类型成为`Eq`的实例，通过以任何他们认为合适的方式，提供在类型`Foo`的值之上的等式函数和不等式函数，例如：

```
data Foo = Foo {x :: Integer, str :: String}
 
instance Eq Foo where
 (Foo x1 str1) == (Foo x2 str2) = (x1 == x2) && (str1 == str2)

```

编程者可以接着如下这样定义函数`elem`，它确定一个元素是否在一个列表之中：

```
elem :: Eq a => a -> [a] -> Bool
elem y [] = False
elem y (x:xs) = (x == y) || elem y xs

```

函数`elem`的类型`a -> [a] -> Bool`具有上下文`Eq a`，将参数多态函数的类型变量`a`可包括的类型，约束为属于`Eq`类型类的那些类型。Haskell中的 `=>` 可表示"类型类继承"或"类型约束"。函数`elem`可应用于属于`Eg`类型类的任何类型的元素和这个类型的列表二者之上。

注意类型类不同于面向对象编程语言中的类。特别是，`Eq`不是一个类型：没有类型`Eq`的值这种东西。类型变量`a`有种类（英语：）（kind）\*，在最新的GHC发行中叫做`Type`。意味着`Eq`的种类是：

```
Eq :: Type -> Constraint

```

高种类多态
-----

类型类不但接受种类（英语：）`Type`的类型变量，它可以接受任何种类的类型变量。这些有更高种类的类型类有时叫做构造子类，这里的构造子指称的是类型构造子比如`Maybe`，而非数据构造子比如`Just`。例如单子类`Monad`：

```
class Monad m where
 return :: a -> m a
 (>>=) :: m a -> (a -> m b) -> m b

```

`m`应用到一个类型变量上的事实，指出了它有着种类`Type -> Type`，就是说它接受一个类型并返回一个类型，因而`Monad`的种类是：

```
Monad :: (Type -> Type) -> Constraint

```

多参数类型类
------

类型类允许多个类型参数，因此类型类可以被看作在类型上的关系。例如，在GHC标准库中，类`IArray`表达一个通用不可变数组接口。在这个类中，类型约束`IArray a e`意味着`a`是一个数组类型，它包含类型`e`的元素。例如，在多态上的这种限制被用来实现开箱（英语：）数组类型。

函数依赖
----

在Haskell中，类型类已经被精制为允许编程者声明在类型参数之间的函数依赖，这个概念受到关系数据库理论中的函数依赖的启发。就是说，编程者可以断言对类型参数的某个子集的给定指派，唯一性的确定余下的类型参数。例如，承载一个类型`s`的状态参数的，一个一般性的单子`m`，满足类型类约束`Monad.State s m`。在这个约束中，有函数依赖`m -> s`。这意味着对于类型类`Monad.State`的一个给定单子`m`，从`m`能访问到的状态类型是被唯一性确定的。这会辅助编译器进行类型推论，还能辅助编程者进行类型导向编程。

Simon Peyton-Jones因其复杂性而反对在Haskell中介入函数依赖。

运算符重载的其他方式
----------

在Standard ML中，"等式类型"的机制粗略的对应于Haskell的内建类型类`Eq`，但是所有等式算符都自动的由编译器导出。编程者的过程控制局限于，指定在一个结构中哪些类型成员是等式类型，和在多态类型中哪些类型变量涉及等式类型。

SML和OCaml的模块和函子可以扮演类似于Haskell的类型类的角色，原则区别在于类型推论的角色，它使得类型类适合于特设多态。OCaml的面向对象子集是某种程度上与类型类有可比性的另一种方式。

有关概念
----

用于重载数据的一个类似概念（实现于GHC中）是类型家族（英语：）。

在Clean中的类型类与Haskell相似，但是有稍微不同的语法。

Rust支持trait，这是具有一致性的有限形式的类型类。

Mercury有类型类，却不完全同于Haskell。

在Scala中，类型类是编程惯例（英语：），可以用现存语言特征比如隐式参数来实现，本身不是独立的语言特征。由于它们在Scala中的这种实现方式，在有歧义的情况下，有可能显式的指定哪种类型类实例用作在代码中特定位置上的类型。但是，这不必然有益处，因为有歧义的类型类实例是易于出错的。

证明辅助Coq在新近版本也支持类型类。不像在平常编程语言中那样，在Coq中，在类型类定义内陈述的任何类型类定律（比如单子定律），在使用它们之前，必须对每个类型类实例进行数学证明。

参见
--

* 多态 (计算机科学)
* 运算符重载 － 类型类的应用之一
* 单子 (函数式编程)，函子 (函数式编程) － 是类型类的例子
* 概念 (C++)（自从C++20）

引用
--

1. ↑  Morris, John.  (PDF). 2013  [2021-02-08]. （原始内容存档 (PDF)于2020-11-04）.
2. ↑  Wadler, Philip.. October 1988.
3. ↑  Kaes, Stefan.. . March 1988. doi:10.1007/3-540-19027-9\_9.
4. ↑  Wadler, Philip; Stephen Blott.. . January 1989  [2021-02-08]. （原始内容存档于2016-03-11）.
5. ↑  Appel, Andrew; David MacQueen.. . June 1991  [2021-02-08]. （原始内容存档于2008-05-09）.
6. ↑  `Type` （页面存档备份，存于） from `Data.Kind` appeared in version 8 of the Glasgow Haskell Compiler
7. ↑  Haskell' page *MultiParamTypeClasses （页面存档备份，存于）*.
8. ↑  Mark Jones. *Type Classes with Functional Dependencies （页面存档备份，存于）*. From Proc. 9th European Symposium on Programming. March, 2000.
9. ↑  Haskell' page *FunctionalDependencies （页面存档备份，存于）*.
10. ↑ .  [2021-02-10]. （原始内容存档于2014-12-25）.
11. ↑  Dreyer, Derek; Robert Harper; Manuel M.T. Chakravarty.. April 2006  [2021-03-01]. （原始内容存档于2007-05-19）.  `|book-title=`被忽略 (帮助)
12. ↑ .  [2021-02-10]. （原始内容存档于2014-10-28）.
13. ↑ .  [2021-02-10]. （原始内容存档于2020-11-12）.

外部链接
----

|  |  |
| --- | --- |
|  | 維基教科書中的相關電子：**类和类型** |

* A Gentle Introduction to Haskell, Version 98, chapter 5. Type Classes and Overloading （页面存档备份，存于）. June 2000.
* Implementing, and Understanding Type Classes （页面存档备份，存于）. 2014-11-13.

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 

| * 
* 论
* 编
数据类型 |
| --- |
|  |
| 无解释的 | 
* 位元
* 字节
* 三进制位
* 三进制字节
* Word

 |
|  |
| 数值 | 
* 整数
	+ 符号性
	+ 有符号数
	+ 无符号数
* 定点数
* 浮点数
	+ 双精度
	+ 扩展精度（英语：）
	+ 半精度
	+ 迷你浮点数（英语：）
	+ 八倍精度（英语：）
	+ 四倍精度（英语：）
	+ 单精度
* 有理数（英语：）
* 复数（英语：）
* 任意精度算术
* 区间（英语：）

 |
|  |
| 文本 | 
* 字符
* 字符串

 |
|  |
| 指针 | 
* 記憶體位址
	+ 物理地址
	+ 虚拟地址
* 參照

 |
|  |
| 组合 | 
* 代数数据类型
	+ 广义（英语：）
* 数组
* 关联数组
* 类
* 串列
* 对象
	+ 元对象
* 可选类型
* 积类型（英语：）
* 记录
* 集合
* 联合体
	+ 标签

 |
|  |
| 其他 | 
* 布尔型
* 底层类别（英语：）
* 容器
* 枚举类型
* 异常
* 一等函数
* 不透明数据类型（英语：）
* 递归数据类型
* 信号标
* 字串流
* 顶类型（英语：）
* 类型类
* 類型系統
* 单位类型（英语：）
* Void
* 不定型別

 |
|  |
| 相关议题 | 
* 抽象資料型別
* 数据结构
* 介面
* 种类（英语：）
* 元类
* 对象类型（英语：）
* 原始型別与複合型別
* 协议
* 子类型
* C++模板
* 型別構造器
* 参数多态

 |

 |