Haskell 是否擦除类型,如果是,这在哪些方面与 Java 中发生的类型擦除相似/不同?
2 回答
警告:经验+推理。请咨询为 The Truth 使用两种编译器的人。
从某种意义上说,类型检查是在编译时完成的,并且类型系统的几个复杂特性被简化为更简单的语言结构,是的,但方式与 Java 完全不同。
类型签名不会产生运行时开销。Haskell 编译器擅长程序转换(它有更多的余地,因为在许多情况下,程序的运行顺序并没有由程序员指定),并且会自动内联适当的定义并将 haskell-polymorhpic (=java-generic) 函数专门用于特定类型等,如果它认为合适的话,如果它有帮助的话。这类似于 Java 类型擦除,但更是如此。
Haskell 中本质上不需要类型转换来确保类型安全,因为 Haskell 被设计成从头开始就是类型安全的。我们不会求助于将所有东西都变成一个对象,我们也不会将它们转换回去,因为多态(通用)函数确实适用于任何数据类型,无论是指针类型还是未装箱的整数,它都能正常工作,没有诡计。因此,与 Java 不同,强制转换不是编译多态(通用)代码的特性。Haskell 的人倾向于认为,如果你在进行类型转换,无论如何你都告别了类型安全。
关于如何在编译时确保代码的静态类型正确性可以避免运行时开销的一个很好的例子,newtype
Haskell 中有一个构造,它是现有类型的类型安全包装器,它被完全编译掉了——所有的构造和破坏都很简单不会在运行时发生。类型系统确保在编译时它被正确使用,它不能在运行时得到,除非使用(类型检查的)访问器函数。
多态(通用)函数没有多态开销。Haskell 重载函数(Java-interface-instance 方法)具有数据开销,因为隐式函数字典用于似乎是对 Java 程序员的后期绑定,但实际上再次在编译时确定。
总结:是的,甚至比在 Java 中更是如此,而且不,它们在运行时从来没有被擦除过。
C and Pascal have type erasure. Java lets you inspect classes at run-time - even dynamically loaded ones!
What Haskell does is much closer to Pascal than to Java.