【问题标题】:What's the difference of a "class" in Haskell and in an "abstract class" in OO language?Haskell 中的“类”和 OO 语言中的“抽象类”有什么区别?
【发布时间】:2010-10-15 01:15:20
【问题描述】:

乍一看,这两种“阶级”有明显的区别。不过,我相信还有更多的相似之处:

  • 两者都有不同类型的构造函数。
  • 两者都定义了一组可应用于特定类型数据的操作,换句话说,它们都定义了一个接口。

我可以看到 Haskell 中的“类”更加简洁,而且效率也更高。但是,我有一种感觉,理论上,“类”和“抽象类”是相同的。

你有什么意见?

【问题讨论】:

    标签: programming-languages haskell functional-programming typeclass


    【解决方案1】:

    呃,不是真的,不。

    一方面,Haskell 的类型类没有构造函数;数据类型。

    此外,类型类实例并没有真正附加到它所定义的类型,它更像是一个单独的实体。您可以分别导入实例和数据定义,通常考虑“这条数据属于哪个类”并没有什么意义。类型类中的函数也没有对定义实例的数据类型的任何特殊访问权限。

    类型类实际上定义的是一组标识符,可以共享这些标识符,以对不同的数据类型进行概念上等效的事情(在某种意义上),在每个类型的显式基础上。这就是为什么它被称为 ad-hoc polymorphism 的原因,与您从常规类型变量中获得的标准 parametric polymorphism 形成对比。

    它更接近于某些语言中的“重载函数”,其中不同的函数被赋予相同的名称,并且调度是基于参数类型完成的(出于某种原因,其他语言通常不允许基于返回的重载类型,尽管这对类型类没有问题)。

    【讨论】:

    • 我会说它们与 Java 中的接口非常相似。
    • @Ionuț G. Stan:当然,在精神上相似,这可能是最不错误的比较。但是,它们的使用方式存在很大差异,因此我不鼓励人们过于关注相似之处,除非作为起点。
    • 我还要补充一点,“精神上”的一个主要区别是,类的特征是类型,而不是对象/值。类陈述关于类型的事实,例如“Int is a Num”或“Maybe is a Functor”。这些是关于类型的陈述,而不是关于“对象”的陈述(例如,“hello”不是 Monoid,它是 String,但 String 是 Monoid)。
    • 我看到的与 Java 相比的唯一区别是,在使用类型类时,您不必为了实现新的类型类而更改类型定义。在 Java 中,您必须更改类定义才能实现新接口。这是我现在能发现的唯一区别。
    【解决方案2】:

    除了实现差异之外,一个主要的概念差异是关于何时声明的类/类型类。

    如果您创建一个新类 MyClass,例如Java 或 C#,您需要在开发类时指定它提供的所有接口。现在,如果您将代码捆绑到一个库中,并将其提供给第三方,它们会受到您决定该类具有的接口的限制。如果他们想要额外的接口,他们必须创建一个派生类,它们的DerivedClass。不幸的是,您的库可能会在不知道派生类的情况下制作副本或 MyClass,并且可能会通过其接口返回新实例,然后它们必须包装这些实例。所以,要真正为类添加新接口,他们必须在你的库之上添加一个全新的层。不优雅,也不实用。

    使用类型类,您可以指定类型提供的与类型定义分开的接口。如果第三方库现在包含 YourType,我可以在我自己的代码中将 YourType 实例化为属于新接口(您在创建类型时未提供)。

    因此,类型类允许该类型的用户控制该类型所遵循的接口,而对于“普通”类,该类型的开发者类是可控的(并且必须拥有水晶球才能看到用户可能想要使用类的所有可能的事情)。

    【讨论】:

    • 其他主要区别:类型类本身不是类型,因此您不能将不同类型与通用接口混合(无论如何不涉及语言扩展);类型类可以基于函数签名中任何位置的类型来定义,而不仅仅是接口中典型的(隐式“this object”)第一个参数。
    【解决方案3】:

    发件人:http://www.haskell.org/tutorial/classes.html

    在继续使用类型类的更多示例之前,有必要指出 Haskell 类型类的另外两个观点。第一个类比面向对象编程(OOP)。在下面关于 OOP 的一般性陈述中,只需将类型类替换为类,将类型替换为对象,就可以得出对 Haskell 类型类机制的有效总结:

    “类捕获通用的操作集。一个特定的对象可能是一个类的实例,并且将有一个对应于每个操作的方法。类可以分层排列,形成超类和子类的概念,并允许继承操作/方法。默认方法也可能与操作相关联。"

    与 OOP 相比,类型不是对象,特别是没有对象或类型内部可变状态的概念。与某些 OOP 语言相比,Haskell 中的方法的一个优势是完全类型安全的:任何将方法应用于类型不在所需类中的值的尝试都将在编译时检测到,而不是在运行时检测到。换句话说,方法不是在运行时“查找”,而是简单地作为高阶函数传递。

    【讨论】:

      【解决方案4】:

      此幻灯片可以帮助您了解 OO 抽象类和 Haskell 类型类之间的异同:Classes, Jim, But Not As We Know Them

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-09-26
        • 2010-10-10
        • 2011-01-24
        • 1970-01-01
        • 2018-10-11
        • 2010-12-12
        • 1970-01-01
        • 2010-12-27
        相关资源
        最近更新 更多