If I'm using a typeclass to overload methods, that's implemented in 'dictionary passing style'. That is, the method gets an extra argument (that doesn't appear in surface Haskell); to resolve overloading the method looks up the dictionary by type of its 'proper' argument(s); and pulls a method implementation out of the dictionary. As described in this q, for example.
But what about typeclasses without methods? They can be used as constraints. Is there a dictionary for them? What does it contain?
For a specific example:
module M where
class C a -- no methods
-- no instances in module M
f :: C a => a -> Bool
f x = blah
There's no instances for C
in this module, so if M
gets imported into some other module (with C
instances) how is f
's dictionary lookup encoded?
The usual situation would be that class C
has method(s); there's calls to them on RHS of the equation for f
; so the wanted C a
is encoded as a dictionary lookup for the method call.
Supplementary q's: (if anybody's still listening)
2a. For no-method typeclasses with superclass constraints: Where do the constraints go in the dictionary? A comment on a ticket from SPJ seems to suggest it's an argument to the dictionary's data constructor.
2b. For no-method typeclass instances with constraints: Again where do the constraints go in the dictionary?
Motivation
@Daniel in the comments is asking the motivation for these q's. Apart from just understanding compiler internals a bit better ...
GHC translates surface Haskell into an Internal Representation: System FC, which has aot explicit type signatures at every function application. (Those applications must include applying to the dictionaries for a class.) I'm trying to understand where all the type-related components of class and instance decls go inside the dictionaries; to figure out how a term in FC gets to an equivalent representation to the original Haskell. Then I don't understand how [typeclasses without methods] fit in. Because those classes cannot appear directly as terms in surface Haskell, but only as constraints. Then it must be dictionar(ies) for such a class that represent it at term level.
If you want to ask where this is going: there seems to be a limitation in FC that it can't represent Functional Dependencies. Something to do with being unable to generate type-level evidence. Then I want to understand how that limitation arises/what about FunDeps can't be (or currently isn't) represented?
f
because there are no instances ofC
. But if you add an instance, sayinstance C Char
, thenf 'a'
works fine. – chepnerf
but I can export it. I deliberately don't want dischargable constraints in this module, so that I force callers off
to access a dictionary. – AntC