与模糊类型的交互
假设你正在引入一类具有字节大小的类型。
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
,明确地说 a
是 Int
。类型应用程序允许我们提供类型参数,即使它没有出现在函数的实际参数中 !