为什么像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 举报,一经查实,本站将立刻删除。