与模糊类型的交互

假设你正在引入一类具有字节大小的类型。

class SizeOf a where
    sizeOf::a -> Int

问题是对于该类型的每个值,大小应该是常量。我们实际上并不希望 sizeOf 函数依赖于 a,而只取决于它的类型。

没有类型应用程序,我们得到的最佳解决方案是像这样定义的 Proxy 类型

data Proxy a = Proxy

此类型的目的是携带类型信息,但没有值信息。然后我们的类看起来像这样

class SizeOf a where
    sizeOf::Proxy a -> Int

现在你可能想知道,为什么不完全抛弃第一个参数?我们的函数的类型就是 sizeOf::Int,或者更准确,因为它是一个类的方法,sizeOf::SizeOf a => Int 或者更加明确的 sizeOf::forall a. SizeOf a => Int

问题是类型推断。如果我在某处写 sizeOf,推理算法只知道我期待一个 Int。它不知道我想用什么类型代替 a。因此,除非启用了 {-# LANGUAGE AllowAmbiguousTypes #-} 扩展,否则编译器会拒绝该定义。在这种情况下,定义编译,它不能在没有歧义错误的情况下在任何地方使用。

幸运的是,类型应用程序的引入节省了一天! 现在我们可以写出 sizeOf @Int,明确地说 aInt。类型应用程序允许我们提供类型参数,即使它没有出现在函数实际参数中