我试图理解如何考虑Haskell中的类型类与Scala中的特征。
我的理解是类型类在Haskell的编译时非常重要,而不再在运行时,另一方面,Scala中的特性在编译时和运行时都很重要。我想用一个简单的例子说明这个想法,我想知道我的观点是否正确。
首先,让我们考虑Haskell中的类型类:
我们举一个简单的例子。类类Eq
。
例如,Int
和Char
都是Eq
的实例。因此,可以创建一个多态List
,它也是Eq
的一个实例,可以包含Int
s或Char
s,但不能同时包含在同一个List中。
我的问题是:这是Haskell 中存在类型类的唯一原因吗?
换句话说,同样的问题:
类型类可以创建多态类型(在此示例中为多态List
),支持在给定类型类中定义的操作(在此示例中,类型类中定义的操作==
{ {1}})但根据我的理解,这是他们存在的唯一理由。我的这种理解是否正确?
(标准)Haskell中是否存在类型类的其他原因?
是否存在其他类型类在标准Haskell中有用的用例?我似乎无法找到任何。
由于Haskell的列表是同构的,因此无法将Eq
和Char
放入同一列表中。因此,根据我的理解,类型类的用处在编译时已经用完了。我的这种理解是否正确?
现在,让我们考虑Scala中类似的List示例:
让我们使用Int
方法定义特征Eq
。
现在让我们equals
和Char
实现特征Int
。
现在可以在Scala中创建一个Eq
,将 List[Eq]
和Char
接入相同列表(注意这一点 - 将不同类型的元素放入同一个List中 - 不可能是Haskell,至少在没有扩展的标准Haskell 98中是不可能的!)
在Haskell列表的情况下,根据我的理解,类型类的存在对于编译时的类型检查是重要的/有用的 非常重要。
相比之下,Scala中traits的存在对于类型检查在编译时是两者是重要的,并且在比较两个列表时对于List中对象的实际运行时类型的多态分派的运行类型是重要的为了平等。
所以,基于这个简单的例子,我来到结论,在Haskell类型类中,主要是在编译时使用/使用,相反,Scala的特性很重要/使用两者在编译时和运行时。
我的结论是否正确?
如果没有,为什么不呢?
编辑:
Scala代码回应n.m.的评论:
Int
打印:
case class MyInt(i:Int) {
override def equals(b:Any)= i == b.asInstanceOf[MyInt].i
}
case class MyChar(c:Char) {
override def equals(a:Any)= c==a.asInstanceOf[MyChar].c
}
object Test {
def main(args: Array[String]) {
val l1 = List(MyInt(1), MyInt(2), MyChar('a'), MyChar('b'))
val l2 = List(MyInt(1), MyInt(2), MyChar('a'), MyChar('b'))
val l3 = List(MyInt(1), MyInt(2), MyChar('a'), MyChar('c'))
println(l1==l1)
println(l1==l3)
}
}
答案 0 :(得分:9)
我将对Haskell方面发表评论。
类型类在Haskell中带来了受限多态性,其中类型变量a
仍然可以被普遍量化,但仅在所有类型的子集上进行范围 - 即,类型为哪个类型类的实例可用。
为什么限制多态性有用?一个很好的例子是等于运算符
(==) :: ?????
它的类型应该是什么?直观地说,它需要两个相同类型的值并返回一个布尔值,所以:
(==) :: a -> a -> Bool -- (1)
但上面的输入并不完全诚实,因为它允许将==
应用于任何类型a
,包括函数类型!
(\x :: Integer -> x + x) == (\x :: Integer -> 2*x)
如果(1)
是(==)
的输入,上面会传递类型检查,因为两个参数的类型都是a = (Integer -> Integer)
。但是,我们无法有效地比较两个函数:众所周知的可计算性结果告诉我们,通常没有算法可以做到这一点。
那么,我们可以做些什么来实现(==)
?
选项1 :在运行时,如果发现函数(或任何其他涉及函数的值 - 例如函数列表)传递给(==)
,则引发例外。这就是例如ML确实如此。尽管在编译时检查类型,但现在键入的程序可能会出现错误"
选项2 :引入一种新的多态,将a
限制为无函数类型。例如,ww可能有(==) :: forall-non-fun a. a -> a -> Bool
,因此比较函数会产生类型错误。 Haskell利用类型类来获得那个。
因此,Haskell类型类允许用户输入(==)
"老实说",确保在运行时没有错误,并且没有过度限制。当然,类型类的功能远不止于此,但至少在我看来,它们的主要目的是以非常通用和灵活的方式允许受限制的多态性。实际上,对于类型类,程序员可以定义自己对通用类型量化的限制。