类型类有什么问题?

Dar*_*rio 15 .net language-agnostic language-design typeclass

类型类似乎很有可能以非常一致,高效和可扩展的方式编写泛型和可重用函数.但仍然没有 "主流语言"提供它们 - 相反:概念,这是一个非常类比的想法,已被排除在下一个C++之外!

反对类型类的原因是什么?显然,许多语言正在寻找一种方法来处理类似的问题:.NET引入了通用约束和类似于IComparable允许函数的接口

T Max<T>(T a, T b) where T : IComparable<T> { // }
Run Code Online (Sandbox Code Playgroud)

对所有实现接口的类型进行操作.

Scala使用traits和所谓的隐式参数/视图边界的组合,它们会自动传递给泛型函数.

但是这里显示的两个概念都有很大的缺点 - 接口是基于继承的,因此由于间接而相对较慢,而且不可能让现有类型实现它们.

如果我们需要一个Monoid的抽象,我们可以很好地编写一个接口并让我们的类型实现它,但内置类型int可能永远不会在你的函数本机上运行.

相反,隐式参数与常规接口/特征不一致.

使用类型类,不会有问题(伪代码)

typeclass Monoid of A where
    static operator (+) (x : A, y : A) : A
    static val Zero : A 
end

instance Int of Monoid where
   static operator (+) (x : Int, y : Int) : Int = x + y
   static val Zero : Int = 0
end
Run Code Online (Sandbox Code Playgroud)

那么我们为什么不使用类型类呢?他们毕竟有严重的劣势吗?

编辑:请不要将类型类与结构类型,纯C++模板或鸭子类型混淆.类型类通过类型显式实例化,而不仅仅是按惯例满足.此外,它可以携带有用的实现,而不仅仅是定义一个接口.

Ste*_*sop 9

概念被排除在外,因为委员会认为它不能及时使它们正确,并且因为它们不被认为对发布至关重要.并不是说他们认为这不是一个好主意,他们只是不认为他们对C++的表达是成熟的:http://herbsutter.wordpress.com/2009/07/21/trip-report/

静态类型试图阻止您将对象传递给函数,这不满足函数的要求.在C++中,这是一个非常重要的事情,因为在代码访问对象的时候,没有检查它是正确的.

Concepts尝试阻止您传递模板参数,该参数不满足模板的要求.但在模板参数是由编译器访问的时候,已经有检查它的正确的事情,即使没有概念.如果您尝试以不支持的方式使用它,则会出现编译器错误[*].在使用大量模板代码的情况下,您可能会获得三个充满尖括号的屏幕,但原则上这是一条信息性消息.在编译失败之前捕获错误的需求不如在运行时未定义行为之前捕获错误的需要紧迫.

通过概念,可以更轻松地指定可在多个实例中工作的模板接口.这很重要,但是比指定可以跨多个调用工作的函数接口要紧迫得多.

在回答你的问题时 - 任何正式声明"我实现这个接口"都有一个很大的缺点,那就是它需要在实现之前发明接口.类型推断系统没有,但它们有一个很大的缺点,即语言一般不能用类型表示整个接口,所以你可能有一个被推断为正确类型的对象,但没有语义归因于那种类型.如果您的语言完全解决了界面(特别是如果它与课程匹配),那么AFAIK你必须在这里采取立场,并选择你的劣势.

[*]通常.有一些例外,例如C++类型系统目前不会阻止您使用输入迭代器,就好像它是一个前向迭代器.你需要迭代器特征.单独打鸭并不能阻止你经过一个走路,游泳和嘎嘎叫的物体,但仔细检查实际上并没有像鸭子那样做任何事情,并且惊讶地发现你认为它会;-)