如何在编译时访问有关值的运行时类型的信息?

时间:2015-02-07 07:04:24

标签: haskell

如何在编译时访问有关值的运行时类型的信息?

例如,如果要询问有关特定属性的运行时类型或使用动态类型。

第4次编辑:这个问题的另一种措辞可以是:""如何在运行时访问有关值的编译时类型的信息?例如,如果您想在运行时询问特定属性或使用动态类型。"

对我来说,这两个表述是等价的,因为据我所知,在纯函数式语言中,所有关于类型的信息在编译时都是已知的。这可能是造成混淆的原因 - 我正在考虑"在编译时可以访问的运行时信息"而大多数人都认为在运行时可以获得编译时信息" :)

2 个答案:

答案 0 :(得分:2)

因为Haskell是强静态类型的,所以传递值的代码通常知道,而不需要查看值,所有它需要知道它是什么类型。

因此,至少在GHC编译器中,Haskell是通过“类型擦除”实现的。这意味着类型值的运行时表示通常不包含有关其类型的信息。这使得表示更加高效和紧凑。

同样在某些情况下,特别是在使用newtype时,它允许在两种类型之间进行转换而绝对没有开销 - 因为两种类型的运行时表示完全相同,值可以在两段代码之间共享,将它们视为不同的类型。

这并不意味着无法在运行时获取有关值类型的编译时信息。但是你必须要求它包含在运行时信息中,而在(GHC)Haskell中这样做的方法是通过Data.Typeable module中的类型Typeable

  • 此类型类为您提供数据类型构造函数的名称,模块名称和包名称以及任何类型参数。
  • 如果您有两个非编译时知道的类型相同但都有Typeable约束的值,则可以在运行时检查它们的类型是否相等。
  • 使用cast,如果它们恰好相同,您也可以在两种类型之间转换值。
  • 但请注意,所涉及的所有类型都必须是单态。你不能 使用它来比较多态函数/值的类型,而不首先将它们专门化为具体的单态类型。

还有类型Dynamic(在Data.Dynamic中),它允许您封装和传递未知但Typeable类型的值。

答案 1 :(得分:1)

您可能正在混合使用类型系统和RTTI /反射的概念。 Haskell不需要像typeid()dynamic_cast()is运算符那样的东西,因为你不能传递一个与函数期望不同的类型的参数(嗯,你可以,但这是通过类型级作弊和不安全来完成的。