HasResolution typeclass
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
I don't understand the p
in the above declaration. Where does it come from and what does it mean?
It's just a proxy.
If you had
class HasResolution a where
resolution :: Integer
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
.
So, one solution was
class HasResolution a where
resolution :: a -> Integer
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
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
).
Then this evolved into
class HasResolution a where
resolution :: p a -> Integer
This means that you aren't tied down to just Proxy
, and it means that if you have, eg, 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.
The first solution is rather dated, though you see examples sometimes. The second and third are rather common. The most recent solution is to enable -XTypeApplications -XAllowAmbiguousTypes
and just have
class HasResolution a where
resolution :: Integer
again, but now -XAllowAmbiguousTypes
staves off the error and -XTypeApplications
lets you specify a
at the call site as resolution @a
. This isn't used as often because it isn't backwards compatible with old code, but you see it more in libraries that require new GHC anyway and can afford to not have compatibility.
上一篇: 如何将选项传递给ChoiceField?