Functional dependencies for typeclasses #3260
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR implements a simple flavor of functional dependencies for typeclasses. A class definition can now be annotated with the
fundeps
attribute, providing a list of the class arguments that are functionally dependent on the rest. For instance, the following definition represents a class of set-like typess
over elements typee
.The fundep attribute is indicating the the 0th argument (
e
) is determined from all other arguments (the complement of the ones listed in the fundep, in this cases
).Assuming we have an instance
setlike a (Set.set a)
, this allows one to write something likeis_empty (add 1 (empty ())
. That would previously fail, sinceis_empty
being called on aSet.set int
, but nothing is constraininge
to beint
. For example we could also haveinstance setlike bool (Set.set int)
, though of course that's not the intention.This change allows the tcresolve to instantiate some uvars in the goal (something we've been prohibiting so far, see #3134, #3130, #2591). I am now allowing this, only for
tcresolve
, since I madetcresolve
aware of uvars and it should not instantiate uvars willy-nilly, it will only ever instantiate the uvars in the fundeps of a goal.There is currently no check for the instances actually respecting the dependencies... so if the user states a functional dependency and does not respect it, some unexpected behavior may occur. This is basically an overlap check which we do not do for non-fundep classes either.
cc @TWal who may find this interesting.