问题描述
我只是查找了HasResolution
typeclass ,它具有单个方法resolution
,该方法声明如下:
I just looked up the HasResolution
typeclass and it has a single method, resolution
that is declared as follows:
class HasResolution a where
...
resolution :: p a -> Integer
我不理解上述声明中的p
.它来自哪里,意味着什么?
I don't understand the p
in the above declaration. Where does it come from and what does it mean?
推荐答案
它只是一个代理.
如果有
class HasResolution a where
resolution :: Integer
您会大吼大叫,因为编译器无法在调用resolution
时推断出您想要的HasResolution
的哪个实例.具体来说,是resolution :: HasResolution a => Integer
,其中a
出现在左侧,而不是出现在右侧,因此您永远无法推断a
.
you'd get yelled at because there is no way for the compiler to ever infer which instance of HasResolution
you want when you call resolution
. Specifically, resolution :: HasResolution a => Integer
, where a
appears on the left but not on the right, so you can never infer a
.
所以,一种解决方法是
class HasResolution a where
resolution :: a -> Integer
和resolution
的文档会说,这并不是要检查a
.这只是为了让编译器找出要选择的实例.您可以将其用作resolution (undefined :: a)
.然后,出现了另一种解决方案:
and resolution
's documentation would say that it is not meant to inspect the a
; it is just meant to let the compiler figure out which instance to pick. You'd use it as resolution (undefined :: a)
. Then, another solution emerged:
data Proxy a = Proxy
class HasResolution a where
resolution :: Proxy a -> Integer
Proxy
不提供任何信息给resolution
;同样,它仅存在于编译器推断a
是什么的情况下.它比原始版本更好,因为resolution
确实无法检查其参数,因此Integer
确实与类型关联,而不与resolution
的参数关联. resolution (Proxy :: Proxy a)
较为冗长(因为不能在Proxy
上实现模式匹配,所以不能仅仅使用undefined
),因此用法稍差一点(或更好,具体取决于您询问的人).
Proxy
gives no information to resolution
; it exists, again, only for the compiler to infer what a
is. It's better than the original in that resolution
really can't inspect its argument, so the Integer
is really associated with the type and not with the argument to resolution
. It's slightly worse (or better, depending on who you ask) in that usage is the more verbose resolution (Proxy :: Proxy a)
(you can't just use undefined
because the implementation may pattern match on Proxy
).
这演变成
class HasResolution a where
resolution :: p a -> Integer
这意味着您不仅仅局限于Proxy
,这意味着,如果您将例如[a]
放在范围内,则可以将其传递给resolution
而不会引起大量的冗长,而保持与刚刚使用Proxy
的代码的兼容性.同样,resolution
的第一个参数仅供编译器使用.这对于实际的实现没有任何意义.您只需使用它来选择所需的HasResolution
的实例.
This means that you aren't tied down to just Proxy
, and it means that if you have, e.g., a [a]
lying in scope, you can pass it to resolution
without incurring massive verbosity, while maintaining compatibility with code that just used Proxy
. Again, resolution
's first argument is for the compiler's use only. It means nothing to the actual implementation. You simply use it to select the instance of HasResolution
you want.
Proxy
最终变得如此普遍,以至GHC.Exts
有了一个新成员: Proxy#
. Proxy#
没有运行时表示形式,因此与Proxy
(或上述多态的p
技巧)不同,它不会造成性能损失.但是,Proxy#
受其类型为forall k. k -> TYPE (TupleRep '[])
的困扰.通过不像其他所有行为良好"的类型一样生活在*
中,它就不能参与多态的p
技巧.
Proxy
eventually became so common that GHC.Exts
got a new member: Proxy#
. Proxy#
has no runtime representation, so it incurs no performance penalty, unlike Proxy
(or the above polymorphic p
trick). Proxy#
, however, suffers from the fact that its kind is forall k. k -> TYPE (TupleRep '[])
. By not living in *
like all the other "well-behaved" types, it cannot participate in the polymorphic p
trick.
class HasResolution a where
resolution :: Proxy# a -> Integer
第一个解决方案是过时的,尽管有时会看到一些示例.第二个和第三个很常见,第四个被最新的解决方案很快取代,最新的解决方案是启用-XTypeApplications -XAllowAmbiguousTypes
并拥有
The first solution is rather dated, though you see examples sometimes. The second and third are rather common, and the fourth was superseded pretty quickly by the most recent solution, which is to enable -XTypeApplications -XAllowAmbiguousTypes
and just have
class HasResolution a where
resolution :: Integer
再次
. -XAllowAmbiguousTypes
避免错误,并且-XTypeApplications
允许您在呼叫站点将a
指定为resolution @a
.不能在需要一定程度向后兼容的代码中使用它,但是在需要新GHC并且负担不起兼容性的库中,您会发现更多.
again. -XAllowAmbiguousTypes
staves off the error and -XTypeApplications
lets you specify a
at the call site as resolution @a
. This can't be used in code that needs to be a certain degree of backwards compatible, but you see it more in libraries that require new GHC anyway and can afford to not have compatibility.
这篇关于HasResolution类型类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!