Haskell是否可以擦除类型信息?

22

Haskell是否会擦除类型,如果是的话,它与Java中发生的类型擦除有何相似之处/差异之处?


同意 - 这篇由Tufts大学的Robert Dockins和Samuel Z. Guyer撰写的有关Haskell字节码验证的论文,也提供了一些在实现Haskell编译器时进行类型擦除的见解。http://www.cs.princeton.edu/~rdockins/pubs/TR-2007-2.pdf - Bittercoder
3
Java中的类型擦除仅限于泛型,允许在运行时检查类型但不能检查泛型类型参数。这样做是为了确保向后兼容性。 - scarfridge
2个回答

37

注意:需要经验和推论。请咨询同时从事编译器的人员以获取真相。

在编译时进行类型检查,并且将类型系统的一些复杂特性简化为更简单的语言结构,这是有点像Java,但方式略有不同。

类型签名不会造成运行时开销。Haskell编译器擅长程序转换(它有更大的自由度,因为运行顺序在许多情况下不是由程序员指定的),并且根据需要自动内联适当的定义并将Haskell多态(=java泛型)函数专门用于特定类型等。这与Java类型擦除类似,但更为突出。

在Haskell中,基本上不需要类型转换来确保类型安全,因为Haskell的设计从根本上就是类型安全的。我们不会把所有东西都变成对象,也不会将它们强制转换回来,因为多态(泛型)函数确实可以处理任何数据类型,无论是指针类型还是未打包的整数,它只是有效工作,而不需要任何技巧。因此,与Java不同,转换不是编译多态(泛型)代码的特征。Haskell人倾向于认为,如果您正在进行类型转换,那么您已经放弃了类型安全。

关于如何在编译时确保代码的静态类型正确性可以避免运行时开销的可爱示例,Haskell中有一个“newtype”构造,它是现有类型的类型安全包装器,并且在完全编译后消失了-所有构造和破坏都不会在运行时发生。类型系统确保在编译时正确使用它,除非使用(经过类型检查的)访问器函数,否则无法在运行时获取到它。

多态(泛型)函数没有多态开销。Haskell重载函数(Java接口实例方法)在某种意义上具有数据开销,因为存在用于看似是Java程序员的后期绑定的隐式函数字典,但实际上也是在编译时确定的。

总结:与Java相比,更是如此,并且从未在运行时擦除。


3
谢谢Andrew,结尾的总结点亮了我的思路...非常清晰易懂的解释。 - Bittercoder

1

C和Pascal具有类型擦除。Java允许您在运行时检查类 - 即使是动态加载的类!

Haskell所做的更接近Pascal而不是Java。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接