什么是Scala的“强大”类型系统?

时间:2011-09-15 14:03:59

标签: scala types

当讨论Scala时,类型系统总是被提到作为主要特征之一。它被称为强大的,并且是语言名字对象的主要原因(Scala是“可伸缩语言”的缩写)。有人可以解释Scala键入的工作方式/为什么这个独特的,以及它如何有助于语言的可扩展性?

5 个答案:

答案 0 :(得分:46)

我不认为现有的答案是恰当的。 Scala有很多便利,但它们与类型系统无关,因为它们与类型有关。事实上,类型推断与类型系统的力量直接冲突 - 如果它不那么强大,可以有完整的类型推断(如在Haskell中)。

所以,

  • Scala有成员的课程。 (很明显,但我想在这里详尽无遗。)
  • scala类的方法(“def”)成员可以有零个或多个参数列表,每个参数列表可以包含零个或多个参数,最后一个参数可能是vararg。
  • 参数可以按值或按名称传递。
  • 参数具有名称,可能具有默认值。
  • Scala有“var”和“val”成员(实际上也是方法)。
  • Scala有“lazy val”成员。
  • Scala具有“类型”成员(类型别名),可以指定为固定类型或类型边界。
  • Scala有抽象类和成员(以上所有成员都可能是抽象的)。
  • Scala有内部类,特征和对象(Scala的内部类与Java不同)。
  • Scala的成员,加上内部的东西,可能会被覆盖。
  • Scala具有类型继承。
  • Scala具有特征,提供类型线性化的多重继承。
  • Scala的traits的方法成员可能有抽象覆盖(可堆叠,类似方面的覆盖)。
  • Scala有单例类型。
  • Scala具有伴侣类/对象(与范围相关)。
  • Scala拥有私人,受保护和公共范围的课程,特征,单身人士和成员。
  • Scala的私有和受保护范围可以限制为任何封闭的包,类,特征或单例,加上“this”。
  • Scala有自我类型。
  • Scala具有类型参数。
  • Scala的类型参数可以是共变量和反变量,也可以是不变量。
  • Scala具有类型构造函数。
  • Scala具有更高阶的类型。
  • Scala有存在类型。
  • Scala具有结构类型。
  • Scala具有隐含参数。
  • Scala有函数类型,因为它们只是一个类加上语法糖,我不认为它属于这个列表。另一方面,函数类型是视图边界的一部分,所以也许它可以。
  • Scala有一个顶部(几乎每个人都有)和一个底部(就像其他静态类型的fp语言一样)。
  • Scala的“单位”是一种带有价值的类型(与其他地方的“无效”相反)。

接下来,有一些与Scala隐含相关的功能,这是上面所包含的功能。

  • Scala具有视图边界,这是一个隐式参数,其作用类似于另一种类型绑定。
  • Scala有上下文counds,一个隐含的参数,就像另一个绑定一样。
  • 一般来说,隐式参数和类型推断可以结合起来构建类型参数的任意复杂证明。

与上一条评论相关,implicits和类型推断一起使Scala的类型系统 turing complete 。也就是说,您将任意程序编码为类型,编译器将在编译时“运行”。证明here,通过SKI微积分,在类型中带有“错误”无限循环作为进一步的演示。

上面的功能列表相当大,令人印象深刻。然而,Scala结合implicits和类型推断的方式在编译时生成静态证明(例如视图边界和上下文边界),这使得Scala的类型系统是唯一的。 AFAIK,没有其他语言可以做到这一点,尽管肯定有其他语言通过其他方式提供证明功能。

答案 1 :(得分:20)

Scala的类型系统优于Java的一些优点:

  1. 在许多情况下可以推断出类型,而不是明确指定。这更方便,但它促进了使用复杂的类型。

    val map = new Map[String, (String, String)]()

    而不是

    Map<String, Tuple<String, String>> map = new HashMap<String, Tuple<String, String>>()

  2. 可以在类型系统中简单表达函数。如果你想看看它有多强大,可以考虑将番石榴库作为Java的解决方案。它令人难以置信的约束和冗长(但仍然有用)。

    val double = (x: Int) => x * 2

    而不是(使用番石榴)

    Function<Integer, Integer> double = new Function<Integer, Integer>() { @Override public Integer apply(Integer value) { return value * 2; }}

  3. 元组是Scala中的一种类型,它绕过了Java只能返回单个值的问题。

  4. Scala支持类型Variances,因此当Cat是Thing的子类型时(或反向关系成立时),您可以指定SomeObject是SomeObject的子类型。在java中,generics are not covariant,这通常是有问题的。

  5. Scala使用traits支持有限形式的多重继承。与接口(其中多个可以用Java实现)不同,traits可以定义方法和变量。

  6. 数组与任何其他类一样透明地处理。

  7. 您可以通过隐式定义添加methods to existing classes。例如,您可以向Arrays of Integers添加“sum”方法。

    class IntArray(value: Array[Int]) { def sumIt = value.reduceRight(_+_) }
    implicit def pimpArray(xs: Array[Int]) = new IntArray(xs)
    Array(1,2,3).sumIt
    
  8. 这是上述某些主题的另一个好资源:http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-5

答案 2 :(得分:6)

除了schmmd的优秀答案外,Scala的类型系统还有更重要的功能:

  • object是Java中static成员变量和方法的干净替代品,例如object有自己的类型,可以作为参数传递
  • type声明:您可以为复杂类型定义别名,例如type FactorMap[A] = Map[A, Set[Int]]
  • 抽象类型成员,作为泛型样式的替代
  • 自我类型
  • 结构类型
  • 用于currying的多个参数列表
  • 隐式参数和转换以及视图边界。这导致了“pimp my library”模式,可以用来模拟Haskell风格的类型类
  • 高阶类型

最后一点是我的最爱之一。例如。你不能用Java编写一个简单的通用仿函数接口。你需要 ......

public interface Function<A,B> {
   public B apply(A a);
}

//not valid Java
public interface Functor<C> {
   public <A,B> C<B> map(Function<A,B> fn, C<A> ca);
}

如果您替换某些具体类型(例如List而不是C),则此方法有效。在Java中,您可以抽象出一个包含的内容(例如,通过编写`List),但是您不能在容器本身上抽象。相信我,我试图找到漏洞(结果是this)。在Scala中,这是一件轻而易举的事:

trait Functor[C[_]] {
   def map[A,B](fn: A => B, ca: C[A]):C[B]
}

object ListFunctor extends Functor[List] {
   def map[A,B](fn: A => B, ca: List[A]):List[B] = ca.map(fn)
}

答案 3 :(得分:3)

任何类型的系统,你可以编码HList,TList和HOF的类型是相当强大的恕我直言。有关详细信息,请参阅http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala/

答案 4 :(得分:0)

我不知道你是否了解Java,但想象Scala的类型系统是这样的:

  • 删除Java对类型和泛型所能做的人为限制
  • 向其添加功能语言的常用功能
  • 创新oop /继承前沿

我会更喜欢o wrie,我的键盘jus坏了,对不起!