c# - 对比 C# 泛型与 Haskell 参数化类型

标签 c# generics haskell polymorphism type-systems

根据我在 StackOverflow 上找到的一些建议,我正在深入研究 Haskell。我很高兴看到 Haskell 的参数化类型表现得非常像 C# 泛型。两种语言都建议使用单个字母作为类型参数(通常),并且两种语言似乎都遵循类似的过程来用实际类型代替类型参数。因此,我很快就理解了这个概念。

这导致了这一点:Haskell 的参数化类型与 C# 泛型类型有哪些不同之处?我从学习 Ruby 的过程中了解到,如果您认为您从一种语言中熟悉的概念在您不熟悉的另一种语言中是相同的,那么您可能会遇到很大的麻烦。通常,当特征实际上非常相似时,问题会更严重……因为它们通常不是 100% 相同。那么,如果我假设我根据我对 C# 泛型的了解了解参数化类型,我可能会遇到哪些“陷阱”?

谢谢。

最佳答案

这里有一个区别需要牢记:

C# 有子类型,但 Haskell 没有,这意味着,一方面,您只需查看 Haskell 类型就可以了解更多内容。

id :: a -> a

这个 Haskell 函数接受一个类型的值并返回相同类型的相同值。 如果你给它一个 Bool,它会返回一个 Bool。给它一个 Int,它会返回一个 Int。给它一个Person,它会返回一个Person

在 C# 中,您不能这么确定。这是 C# 中的“函数”:

public T Id<T>(T x);

现在,由于子类型化,你可以这样调用它:

var pers = Id<Person>(new Student());

虽然 persPerson 类型,但 Id 函数的参数不是。事实上 pers 可能有一个比 Person 更具体的类型。 Person 甚至可以是抽象类型,保证 pers 将具有更具体的类型。

如您所见,即使使用像 id 这样简单的函数,.NET 类型系统也已经比 Haskell 中更严格的类型系统允许更多的功能。虽然这可能对某些编程工作有用,但它也使得仅通过查看事物的类型来推理程序变得更加困难(这在 Haskell 中是一种乐趣)。


第二件事,Haskell 中有特别多态性(又名重载),通过一种称为“类型类”的机制。

equals :: Eq a => a -> a -> Bool

此函数检查两个值是否相等。但不仅仅是任意两个值,只是具有 Eq 类实例的值。这有点像 C# 中类型参数的约束:

public bool Equals<T>(T x, T y) where T : IComparable

但是,还是有区别的。一方面,子类型化:您可以使用 Person 实例化它并使用 StudentTeacher 调用它。

但是编译的结果也有区别。 C# 代码几乎完全按照它的类型编译。类型检查器确保参数实现正确的接口(interface),并且比你好。

而 Haskell 代码符合如下内容:

equals :: EqDict -> a -> a -> Bool

该函数获得一个额外参数,这是一个包含执行Eq 操作所需的所有函数的字典。以下是您可以如何使用此函数,以及它编译后的结果:

b1 = equals 2 4          --> b1 = equals intEqFunctions 2 4
b2 = equals True False   --> b2 = equals boolEqFunctions True False

这也说明了是什么让子类型变得如此痛苦,想象一下如果可能的话。

b3 = equals someStudent someTeacher
     --> b3 = equals personEqFunctions someStudent someTeacher

personEqFunctions 字典应该如何确定 Student 是否等于 Teacher?他们甚至没有相同的字段。

简而言之,虽然乍一看 Haskell 类型约束可能看起来像 .NET 类型约束,但它们的实现方式完全不同,并且编译成两个完全不同的东西。

关于c# - 对比 C# 泛型与 Haskell 参数化类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/720517/

相关文章:

java - 如何使用 java 中的反射确定泛型类型的构造函数参数数量?

具有参数化类型的 Java getConstructor(types)

haskell - 在 catamorphism 中组合 f-代数的规则是什么

scala - 名称值/表达式保存在函数程序中的什么位置?

haskell - 为什么 Haskell 中没有 IO 转换器?

c# - 如何获取单选按钮列表的文本?

C# 在不同程序集中定义重写方法

c# - 当我需要传入 HttpResponse 时,如何测试第三方框架

c# - 在 C# 中实现通用对象比较

c# - 匹配大写字母、数字或大写、小写和数字的正则表达式