实例在Haskell中意味着什么?

Aug*_*son 13 haskell functional-programming typeclass

在Java中,我们可以从类中创建对象/实例.在Haskell中,我们可以从类型类创建实例,例如:

data ShirtSize = S | M | L      -- Here ShirtSize is a enum data-type

class MyEq a where
  (==) :: a -> a -> Bool
instance MyEq ShirtSize where   -- Here ShirtSize is an instance of the MyEq type-class
  S == S = True
  M == M = True
  L == L = True
  _ == _ = False
Run Code Online (Sandbox Code Playgroud)

这不是同一个问题:在haskell Obs中混淆函数作为functor的实例:我不是在问fmap是如何工作的,我在问Haskell中的实例解法是什么意思.

我的问题是: 实例在haskell中意味着什么?在java中我们可以从类中创建实例,但在haskell中,似乎实例是类型(如ShirtSize),您可以在其上应用类型类函数(例如,来自MyEq 的(==)函数).我对吗?还有什么是Haskell中的实例与Java中的实例/对象相比?

n. *_* m. 16

在Java中,类系统是一种对类似对象进行分组的方法.类的实例是属于该类的单个对象.

在Haskell中,类系统(粗略地说)是一种对类似类型进行分组的方法.(这就是我们称之为"类型类"的原因).类的实例是属于该类的单个类型.(也就是说,直到你开始考虑多参数类型).

顺便提一下,Haskell(单参数)类有点类似于Java接口,并且通过扩展,类似于Java类.或许Haskell实例类似于Java类.最好将此视为巧合.接近保持其数学起源的术语.一个类只是一堆属于一起的东西,一个实例就是其中之一.


She*_*rsh 7

如果您对类型类的解释和Java接口的不同感兴趣,您应该通过<❤>阅读这篇文章.它也解释了实例.

至于我,我instance看作数据类型和接口之间的连接.data包含一些信息,class包含方法.data是关于数据(抱歉重言论),class是关于行为.当您查看数据类型时,您看不到可以使用它做什么,而是看到它存储的内容.当你看到class你看到应该能够做什么类型时,你不关心它在内部存储什么.在实际编程中,您实际上关心的是实现细节以及如何使用特定数据实现方法.因此,instance只显示某些数据与某些行为之间的关系 - 如何使用给定数据实现此行为.

如果您对类型类的模型感兴趣,请阅读以下博客文章:http://www.haskellforall.com/2012/05/scrap-your-type-classes.html

您可以将实例视为值!如果你第一次面对这样的定义,它可能会让你大吃一惊.

在某些依赖类型的语言instances中,您可以传递给其他函数的值.看看这个问题:

在Idris中,"Eq a"是一种类型,我可以为它提供一个值吗?


小智 5

看起来实例是类型(如 ShirtSize),您可以在其上应用类型类函数(例如 MyEq 中的 (==) 函数)

完全正确。

在 Haskell 中,类型是定义的数据结构。Haskell 代码中存在的每个值都有一个定义的类型。并且类型可以成为类的实例,这意味着......实际上,请保持这种想法。我想谈谈功能。

函数具有类型签名,定义它们可以使用的类型。如果函数被定义为处理特定类型,则该函数可以用于具有该类型的任何值。如果函数被定义为在特定上工作,那么它可以用于该类实例的任何类型的任何值。

当您定义一个类时,您描述了一些最小的函数集(例如==在您的示例中),这些函数必须为所有想要成为该类实例的类型实现。该类定义了这些函数的名称和签名,并且该定义意味着这些名称和签名是固定的。对于该类的每个实例,它们都是相同的。

但类并没有修复这些实现。对于不同的类型,它们可以是不同的。我们通过编写实例语句将类型创建为类的实例,在其中我们可以定义这些函数将如何工作。如果类提供函数的默认实现,则不同的实例类型可以覆盖默认值并拥有自己的定义。如果没有默认值,则实例类型必须有自己的定义。

现在您拥有了一组最小的函数,可以使用任何类型的任何值来调用这些函数。您可以通过调用这些函数来编写更多的函数,并从那里进行构建。

这个想法确实有用,但恕我直言,术语很糟糕。说这些类型是类的实例,听起来好像它们是子类型或子类型,从父类型继承属性。但事实根本不是那样的。作为一个类的实例就像是一个俱乐部的成员。许多不同的、不相关的类型都可以是同一类的实例。一种类型可以同时是许多不同的不相关类的实例。

在 Rust 中,他们有相同的想法,但是用“trait”这个词而不是“class”。他们不会说“此类型是该类的实例”,而是说“此类型实现了该特征”。我认为这样可以更好地传达这个想法。