scala - Haskell 中类型类的目的与 Scala 中特征的目的

标签 scala haskell typeclass traits

我试图了解如何考虑 Haskell 中的类型类与 Scala 中的特征。

我的理解是,类型类在 Haskell 的编译时主要是重要的,而不是在运行时,另一方面,Scala 中的特征在编译时和运行时都很重要。我想用一个简单的例子来说明这个想法,我想知道我的这个观点是否正确。

首先,让我们考虑一下 Haskell 中的类型类 :

让我们举一个简单的例子。类型类Eq .

例如,IntChar都是 Eq 的实例.因此可以创建多态List这也是 Eq 的一个实例并且可以包含 Int s 或 Char s 但不是两者都在同一个列表中。

我的问题是:这是 Haskell 中存在类型类的唯一原因吗 ?

换句话说,同样的问题:

类型类能够创建支持在给定类型类中定义的操作的多态类型(在本例中为多态 List)(在本例中为在类型类 == 中定义的操作 Eq),但这是它们的根据我的理解,唯一存在的理由。我的这种理解正确吗?

(标准)Haskell中存在类型类还有其他原因吗?

在标准 Haskell 中是否还有其他类型类有用的用例?我似乎找不到任何东西。

由于 Haskell 的列表是同质的,因此无法放入 CharInt进入同一个列表。所以根据我的理解,类型类的用处在编译时就用完了。我的这种理解正确吗?

现在,让我们考虑 Scala 中类似的 List 示例:

让我们定义一个特征 Eqequals方法就可以了。
现在让我们制作CharInt实现特征 Eq .

现在可以创建 List[Eq]在接受 的 Scala 中两个 Char s 和 Int进入相同列表 (请注意,这 - 将不同类型的元素放入同一个列表 - Haskell 是不可能的,至少在没有扩展的标准 Haskell 98 中是不可能的)!

在 Haskell 列表的情况下,类型类的存在很重要/有用仅限 根据我的理解,在编译时进行类型检查。

相比之下,Scala 中特征的存在很重要 两个在比较两个列表是否相等时,在编译时进行类型检查,在运行时对列表中对象的实际运行时类型进行多态分派(dispatch)。

所以,基于这个简单的例子,我来到了结论 在 Haskell 中,类型类主要在编译时很重要/使用,相比之下,Scala 的特征很重要/使用 两个在编译时和运行时。

我的这个结论正确吗?

如果不是,为什么不呢?

编辑:

响应 n.m. 评论的 Scala 代码:

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)
  }
}

这打印:
true
false

最佳答案

我将评论 Haskell 方面。

类型类在 Haskell 中带来了受限的多态性,其中类型变量 a仍然可以普遍量化,但仅涵盖所有类型的一个子集——即类型类的实例可用的类型。

为什么受限多态性有用?一个很好的例子是相等运算符

(==) :: ?????

它的类型应该是什么?直观地说,它接受两个相同类型的值并返回一个 bool 值,所以:

(==) :: a -> a -> Bool         -- (1)

但是上面的输入并不完全诚实,因为它允许一个人申请 ==任何类型a ,包括函数类型!

(\x :: Integer -> x + x) == (\x :: Integer -> 2*x)

如果 (1),以上将通过类型检查是 (==) 的输入吗? , 因为两个参数的类型相同 a = (Integer -> Integer) .但是,我们无法有效地比较两个函数:众所周知的 Computability 结果告诉我们,一般来说没有算法可以做到这一点。

那么,我们可以做些什么来实现 (==) ?

选项 1 : 在运行时,如果发现一个函数(或任何其他涉及函数的值——例如函数列表)被传递给 (==) ,引发异常。这就是例如机器学习做到了。尽管在编译时检查类型,但类型化程序现在可能“出错”。

选项 2 :引入一种新的多态性,限制a到无功能类型。例如,ww 可以有 (==) :: forall-non-fun a. a -> a -> Bool这样比较函数就会产生类型错误。 Haskell 利用类型类来准确地获得它。

因此,Haskell 类型类允许键入 (==) “老实说”,确保在运行时没有错误,并且没有过度限制。当然,类型类的威力远不止于此,但至少在我自己看来,它们的主要目的是以一种非常通用和灵活的方式允许受限制的多态性。事实上,使用类型类,程序员可以定义他们自己对通用类型量化的限制。

关于scala - Haskell 中类型类的目的与 Scala 中特征的目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25956658/

相关文章:

haskell - `join` 和 `fmap join` 在 Haskell 中是否相等(从范畴论的角度来看)?

Scala:为反射/运行时实例使用正确的类型类实例

haskell - 没有方法的类型类,用作约束 : do they get dictionaries?

Spark 中 Scala 的收集效率低下?

scala - scala 解决隐式值冲突的规则是什么

java - 如何在 Scala 中使用可变参数方法实现 Java 接口(interface)?

java - Main(args) 包含多个数组

haskell - haskell 中的顶级可变变量

haskell - 在 Haskell 中反转二进制数

scala - 实现某个类型类的类列表