微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么Scala允许嵌套数据结构,如List或Array

为什么像Scala这样的语言,使用非常强大的静态类型系统,可以允许以下结构:

scala> List(1,List(1,2))
 res0: List[Any] = List(1,2))

如果您使用Array替换List,同样的事情将会起作用.我学习了OCaml中的功能编程,它将在编译时拒绝相同的代码

# [1; [1;2]; 3];;
Characters 4-9:
  [1; [1;2]; 3];;
      ^^^^^
Error: This expression has type 'a list
       but an expression was expected of type int

那么为什么Scala允许这样编译?

解决方法

TL;博士

长篇小说,OCaml和Scala使用两种不同类型的系统:前者具有structural typing,后者具有nominal typing,因此它们在类型推理算法方面表现不同.

全面讨论

如果您在系统中允许使用nominal subtyping,这几乎是你得到的.

在分析列表时,Scala编译器会将类型计算为列表包含的所有类型的LUB(最小上限).在这种情况下,Int和List的LUB是Any.其他情况会有更明智的结果:

@ List(Some(1),None)
res0: List[Option[Int]] = List(Some(1),None)

一些[Int]和None的LUB是Option [Int],这通常是你期望的.如果用户失败,则对用户来说将是“奇怪的”

expected List[Some[Int]] but got List[Option[Int]]

OCaml使用structural subtyping,因此其类型系统在类型推断方面的工作方式不同.正如@gsg在评论中指出的那样,OCaml并不统一Scala类型,而是需要一个明确的上线.

在Scala中,编译器在执行类型推断时统一类型(由于名义子类型).

当然,您可以通过显式类型注释获得更好的错误

@ val x: List[Int] = List(1,2))
Compilation Failed
Main.scala:53: type mismatch;
 found   : List[Any]
 required: List[Int]
}.apply
  ^

只要编译器使用-Ywarn-infer-any标志来推断Any – 通常是一个坏的标志,就可以得到警告.以下是Scala REPL的示例:

scala -Ywarn-infer-any
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM,Java 1.8.0_51).
Type in expressions to have them evaluated.
Type :help for more information.

scala> List(1,2))
<console>:11: warning: a type was inferred to be `Any`; this may indicate a programming error.
       List(1,2))
            ^
res0: List[Any] = List(1,2))

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐