HasResolution typeclass
我刚刚抬头的HasResolution
类型类,它有一个方法, resolution
该声明如下:
class HasResolution a where
...
resolution :: p a -> Integer
我不明白上述声明中的p
。 它来自哪里,它是什么意思?
这只是一个代理。
如果你有
class HasResolution a where
resolution :: Integer
你会大声吼叫,因为编译器无法推断你调用resolution
时需要的HasResolution
实例。 具体来说, resolution :: HasResolution a => Integer
,其中a
出现在左侧,但不是右侧,所以你永远不能推断出a
。
所以,一个解决方案是
class HasResolution a where
resolution :: a -> Integer
resolution
的文件会说它并不是要检查a
; 它只是为了让编译器找出选择哪个实例。 你会用它作为resolution (undefined :: a)
。 然后出现了另一个解决方案
data Proxy a = Proxy
class HasResolution a where
resolution :: Proxy a -> Integer
Proxy
不提供resolution
信息; 它的存在,再次,只为编译器推断出a
的。 它比原来更好,因为该resolution
实际上无法检查它的论点,所以Integer
与类型有关,而与resolution
的论点没有关系。 它稍差(或更好,取决于你问谁),这是更详细的resolution (Proxy :: Proxy a)
(你不能只使用undefined
因为实现可能在Proxy
上模式匹配)。
然后这演变成了
class HasResolution a where
resolution :: p a -> Integer
这意味着,你不依赖下降到只有Proxy
,这意味着,如果你有,例如, [a]
躺在范围,你可以把它传递给resolution
,而不会产生大量的冗长,同时保持代码的兼容性,仅仅使用Proxy
。 同样, resolution
的第一个参数是仅供编译器使用。 这对于实际的实施没有任何意义。 您只需使用它来选择您想要的HasResolution
实例。
第一个解决方案相当过时,有时候你会看到例子。 第二和第三是相当普遍的。 最近的解决方案是启用-XTypeApplications -XAllowAmbiguousTypes
并且具有
class HasResolution a where
resolution :: Integer
再次,但现在-XAllowAmbiguousTypes
避开错误, -XTypeApplications
允许您在调用站点指定a
作为resolution @a
。 这并不经常使用,因为它不会与旧代码向后兼容,但是您仍然可以在需要新的GHC的库中看到它,并且可以承受不兼容。