jhe*_*dus 11 haskell scala traits typeclass
我试图理解如何考虑Haskell中的类型类与Scala中的特征.
我的理解是类型类是在Haskell的编译时间在运行时主要是重要的,而不是了,在斯卡拉另一方面特质都很重要在编译时间和运行时间.我想用一个简单的例子说明这个想法,我想知道我的观点是否正确.
首先,让我们考虑Haskell中的类型类:
我们举一个简单的例子.类型类Eq.
例如,Int并且Char都是Eq.的实例.因此,可以创建一个多态List,它也是一个实例,Eq并且可以包含Ints或Chars,但不能同时包含在同一个List中.
我的问题是:这是Haskell中存在类型类的唯一原因吗?
换句话说,同样的问题:
类型类可以创建多态类型(在这个例子中是一个多态List),它支持在给定类型类中==定义的操作(在这个例子中是类型类中定义的操作Eq),但这是它们存在的唯一原因,根据我的理解.我的这种理解是否正确?
是否存在(标准)Haskell中存在类型类的任何其他原因?
是否有其他用例,其中类型类在标准Haskell中有用?我似乎找不到任何东西.
由于Haskell的列表是同构的,因此无法放入Char和Int放入相同的列表.因此,根据我的理解,类型类的用处在编译时已经用完了.我的这种理解是否正确?
现在,让我们考虑Scala中的类似List示例:
让我们Eq用一个equals方法定义一个特征.现在让我们制作Char并Int实现这个特性Eq.
现在可以创建一个List[Eq]Scala中接受两个 Char S和IntS插入相同的列表(请注意,这-把不同类型的元素融入到同一个列表-是不可能的Haskell,至少不是标准的Haskell 98没有扩展名)!
在Haskell的列表的情况下,类型阶级的存在是很重要/有用的只有类型在编译时检查,根据我的理解.
相比之下,性状在斯卡拉的存在是非常重要的两个比较两个列表相等时,在编译时进行类型检查,并在运行类型上的实际运行时类型在列表中的对象的多态分派.
因此,基于这个简单的例子,我来到了结论,即在Haskell类型类主要是重要的/在编译时使用,相反,Scala的特征是重要的/使用都在编译时和运行时.
我的这个结论是否正确?
如果没有,为什么不呢?
编辑:
Scala代码响应nm的评论:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
这打印:
true
false
Run Code Online (Sandbox Code Playgroud)
我将评论Haskell方面.
类型类在Haskell中带来了受限制的多态性,其中类型变量a仍然可以被普遍量化,但是仅在所有类型的子集上 - 即,类型类的实例可用的类型.
为什么限制多态是有用的?一个很好的例子是相等运算符
(==) :: ?????
Run Code Online (Sandbox Code Playgroud)
它的类型应该是什么?直观地说,它需要两个相同类型的值并返回一个布尔值,因此:
(==) :: a -> a -> Bool -- (1)
Run Code Online (Sandbox Code Playgroud)
但上面的输入并不完全诚实,因为它允许应用于==任何类型a,包括函数类型!
(\x :: Integer -> x + x) == (\x :: Integer -> 2*x)
Run Code Online (Sandbox Code Playgroud)
如果(1)输入的话,上面会传递类型检查(==),因为两个参数的类型相同a = (Integer -> Integer).但是,我们无法有效地比较两个函数:众所周知的可计算性结果告诉我们,通常没有算法可以做到这一点.
那么,我们可以做些什么(==)呢?
选项1:在运行时,如果发现函数(或任何其他涉及函数的值 - 例如函数列表)被传递给(==),则引发异常.这就是ML所做的.尽管在编译时检查类型,但现在键入的程序可能"出错".
选项2:引入一种新的多态,限制a为无函数类型.例如,ww可以(==) :: forall-non-fun a. a -> a -> Bool使比较函数产生类型错误.Haskell利用类型类来获得它.
因此,Haskell类型类允许人们(==)"诚实地"输入,确保在运行时没有错误,并且没有过度限制.当然,类型类的功能远不止于此,但至少在我看来,它们的主要目的是以非常通用和灵活的方式允许受限制的多态性.实际上,对于类型类,程序员可以定义他们自己对通用类型量化的限制.