Files
mercury/tests/valid/fundeps_poly_instance.m
Mark Brown 2c8630fdde Support polymorphic instances of typeclasses with functional dependencies.
Estimated hours taken: 16
Branches: main

Support polymorphic instances of typeclasses with functional dependencies.
We do this by allowing type variables in the range arguments, which must be
distinct according to existing typeclass restrictions, to be determined
from type variables in the domain arguments by the functional dependencies
on the instance constraints.

compiler/check_typeclass.m:
	Remove the range-restrictedness check and replace it with a coverage
	check, which makes use of the instance constraints when determining
	if a type variable is bound.

	Explicitly pass the range tvars to get_unbound_tvars, so that it
	can be used by the coverage pass as well as the
	check_typeclass_constraints pass.

	Rearrange the structure of the module, since multiple passes now
	make use of the get_unbound_tvars predicate.  Separate out the
	error reporting code from the main logic.

	Clarify the description at the top of this module.  It now corresponds
	more closely with the structure of the module.

	Fix a bug in check_instance_pred_procs/12 whereby the wrong context
	was being used in the new instance definition, leading to incorrect
	error messages; use field update syntax to avoid this problem.

doc/reference_manual.texi:
	Add an example to illustrate the relaxed restrictions.

tests/valid/Mmakefile:
tests/valid/fundeps_poly_instance.m:
	Test the new feature.

tests/invalid/Mmakefile:
tests/invalid/fundeps_coverage.err_exp:
tests/invalid/fundeps_coverage.m:
	Test the new error reporting.

tests/invalid/range_restrict.err_exp:
	Update for the changed error message.

tests/invalid/typeclass_bogus_method.err_exp:
tests/invalid/typeclass_test_10.err_exp:
	Update these expected outputs for the bugfix.
2006-10-29 03:18:59 +00:00

27 lines
779 B
Mathematica

:- module fundeps_poly_instance.
:- interface.
:- typeclass foo(A, B) <= (A -> B) where [].
:- typeclass bar(A, B, C) <= foo(A, B) where [].
:- typeclass baz(A, B, C) <= ((A -> B, C), bar(A, B, C)) where [].
:- implementation.
:- type t(T) ---> t(T).
% B is in the range of the functional dependency we must satisfy,
% but it is determined from A by the functional dependencies on the
% constraint.
%
:- instance foo(t(A), t(B)) <= foo(A, B) where [].
:- instance bar(t(A), t(B), t(C)) <= foo(A, B) where [].
% B and C are in the range of the functional dependency we must
% satisfy. B is determined from the foo/2 constraint, and C is
% determined by an ancestor of the bar/3 constraint.
:- instance baz(t(A), t(B), t(C)) <= (foo(A, B), bar(B, C, A)) where [].