这里要记住的一个区别:
c#子类型化,但Haskell没有,这意味着,首先,你< em > < / em >知道更多的事情,只要看着Haskell类型。
id :: a -> a
This Haskell function takes a value of a type and returns that same value of that same type.
If you give it a Bool
, it will return a Bool
. Give it a Int
, it will return a Int
. Give it a Person
, it will return a Person
.
在c#中,您可以不那么肯定。这是用c#函数:
public T Id<T>(T x);
现在,因为子类型化的你可以叫它像这样:
var pers = Id<Person>(new Student());
而<代码>珀耳斯> < /代码类型的<代码> < /代码>,<代码> Id的参数不是> < /代码功能。事实上<代码>心> < /代码可能有一个更具体的类型不仅仅是<代码> < /代码>的人。<代码> > < /代码的人甚至可以是一个抽象的类型,保证<代码>心> < /代码将有一个更具体的类型。
正如你所看到的,即使有一个函数简单<代码> id > < /代码。net类型系统已经允许更多比严格的类型系统从<代码> Haskell > < /代码。虽然这可能是有用的做一些编程工作,也很难推断程序通过看一个事物的类型(在Haskell是一种乐趣)。
第二件事,有< em > < / em >特别在Haskell多态性(又名重载),通过一个机制称为类型类。
equals :: Eq a => a -> a -> Bool
这个函数检查两个值是否相等。但不是任何两个值,只是有实例的值<代码> Eq > < /代码类。这是有点像限制在c#类型参数:
public bool Equals<T>(T x, T y) where T : IComparable
然而,有一个区别。首先,子类型化:你可以实例化它与<代码> < /代码>,和<代码>学生称之为< /代码>和<代码>教师> < /代码。
但还有一个区别在这编译。c#代码编译几乎说什么其类型。类型检查器确保参数实现适当的接口,和比你好的。
而Haskell代码符合这样的:
equals :: EqDict -> a -> a -> Bool
函数得到一个< em > < / em >额外的参数,一个字典的所有功能需要做<代码> 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 > < /代码字典应该看看<代码>学生< /代码> = <代码>老师> < /代码?他们甚至不具有相同的字段。
简而言之,在Haskell类型约束一见钟情的样子。net类型约束,实现它们完全不同,编译两个非常不同的事情。