类型类和代数数据类型之间的区别

Pun*_*nGy 4 haskell functional-programming scala fantasyland

据我了解,类型类不是具体的东西,而只是临时和参数多态性的构造。EqSemigroup是类型类的示例。另一方面,代数数据类型是一种具体的复合类型,例如EitherMaybe。他们也是函子

因此,JavaScript 有一个代数数据类型规范: https: //github.com/fantasyland/fantasy-land。在本页中,Setoid (Eq)、OrdSemigroup也是 ADT。但这是正确的吗?如果是这样,它们由什么类型组成?

我还找到了这篇关于类型类的文章,这里 Functor 和 Monad 是类型类。https://typelevel.org/cats/typeclasses.html#type-classes-in-cats。而且,这是否意味着EitherMaybe也是类型类?

Eq是类型还是代数数据类型?或两者?函子也一样

Lui*_*rez 10

造成困惑的根本原因在于区分概念和实现。
因此,让我们尝试使其中一些内容更加清晰。

类型类

是一种模式,实现多态性;准时,即席多态性。

在某些语言中,这些是该语言提供的功能;例如HaskellRust
其他,允许您使用其他功能来表达它们;例如Scala使用隐式,这意味着它们是该语言中的值,而它们不是Rust中的值 (据我所知)
最后,理论上,您可以用任何语言对它们进行建模,但您需要手动传递实例,这就是通常称为策略模式;Java就是一个例子Comparator。有些人认为,如果必须显式传递该值,那么它就不是类型类,我个人不同意,但我们不要打开潘多拉魔盒。

代数数据类型 (ADT)

是一种基于简单构造函数(称为产品和联合)的数据建模模式。

同样,某些语言为开箱即用的语言提供了构建块,例如Haskell。其他一些在编译器的帮助下在经典子类型和对象上模拟它们,例如Scala
而且,理论上您可以用任何语言对它们进行建模,并将模式匹配替换为fold. 但是,在这种情况下,我确实同意,如果 UX 不愉快并且语言中没有内置模式匹配,则很难谈论 ADT。

函子

是一个抽象概念,是从范畴论派生出来的一个概念。
本质上,它由三部分组成:

  • F[_]类型的类型(* -> * 通常称为类型构造函数);例如List
  • map[A, B](fa: F[A])(f: A => B): F[B]给定类型的实现F
  • 证明此类实施符合法律的正式证明Functor

我不会尝试解释 aFunctor在这里是什么......
但是,快速 TL;DR; 是它代表了通过将函数应用于它将计算的值来转换某些上下文的可能性。

由于 aFunctor是一个抽象,我们需要某种形式的多态性来表示它。经验告诉我们,类型类是对 、 、 等进行建模的最自然的方式。Functor但是MonadMonoid您可以尝试使用其他方法,例如结构类型或子类型...但实际上,您会比后者更快地碰壁。

附加功能

最重要的是,我们还需要添加每种语言可能具有的其他间接层。
例如,在Scala中,我们使用子类型来建模类型类层次结构,因此Monad[F] extends Functor[F]和相同的关键字来建模子类型抽象和类型类抽象trait

再次强调,始终将概念/想法与其底层实现分开是很重要的;归根结底,一切都将只是一台奇怪机器上的电脉冲:p