From 0fcf060418167e05adfbde174b2f030077cb1c1b Mon Sep 17 00:00:00 2001 From: Simon Peyton Jones Date: Tue, 15 Jul 2014 17:40:39 +0100 Subject: Improve documentation of overlapping instances (again) Prompted by Trac #9288 --- docs/users_guide/glasgow_exts.xml | 128 ++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 55 deletions(-) (limited to 'docs') diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index 85c8a80bf2..9acb56fc29 100644 --- a/docs/users_guide/glasgow_exts.xml +++ b/docs/users_guide/glasgow_exts.xml @@ -5011,7 +5011,8 @@ with N. In general, as discussed in , GHC requires that it be unambiguous which instance declaration -should be used to resolve a type-class constraint. This behaviour +should be used to resolve a type-class constraint. +This behaviour can be modified by two flags: -XOverlappingInstances @@ -5020,6 +5021,8 @@ and , as this section discusses. Both these flags are dynamic flags, and can be set on a per-module basis, using an LANGUAGE pragma if desired (). + + The flag instructs GHC to loosen the instance resolution described in , by @@ -5027,18 +5030,83 @@ allowing more than one instance to match, provided there is a most specific one. The flag further loosens the resolution, by allowing more than one instance to match, irespective of whether there is a most specific one. +The flag implies the + flag, but not vice versa. -For example, consider +A more precise specification is as follows. +The willingness to be overlapped or incoherent is a property of +the instance declaration itself, controlled by the +presence or otherwise of the +and flags when that instance declaration is +being compiled. Now suppose that, in some client module, we are searching for an instance of the +target constraint (C ty1 .. tyn). +The search works like this. + + +Find all instances I that match the target constraint; +that is, the target constraint is a substitution instance of I. These +instance declarations are the candidates. + + + +Find all non-candidate instances +that unify with the target constraint. +Such non-candidates instances might match when the target constraint is further +instantiated. If all of them were compiled with +, proceed; if not, the search fails. + + + +Eliminate any candidate IX for which both of the following hold: + + +There is another candidate IY that is strictly more specific; +that is, IY is a substitution instance of IX but not vice versa. + +Either IX or IY was compiled with +. + + + + + + +If only one candidate remains, pick it. +Otherwise if all remaining candidates were compiled with +, pick an arbitrary candidate. + + + +These rules make it possible for a library author to design a library that relies on +overlapping instances without the library client having to know. + + +Errors are reported lazily (when attempting to solve a constraint), rather than eagerly +(when the instances themselves are defined). So for example + + instance C Int b where .. + instance C a Bool where .. + +These potentially overlap, but GHC will not complain about the instance declarations +themselves, regardless of flag settings. If we later try to solve the constraint +(C Int Char) then only the first instance matches, and all is well. +Similarly with (C Bool Bool). But if we try to solve (C Int Bool), +both instances match and an error is reported. + + + +As a more substantial example of the rules in action, consider instance context1 => C Int b where ... -- (A) instance context2 => C a Bool where ... -- (B) instance context3 => C a [b] where ... -- (C) instance context4 => C Int [Int] where ... -- (D) -compiled with enabled. The constraint -C Int [Int] matches instances (A), (C) and (D), but the last +compiled with enabled. Now suppose that the type inference +engine needs to solve The constraint +C Int [Int]. This constraint matches instances (A), (C) and (D), but the last is more specific, and hence is chosen. If (D) did not exist then (A) and (C) would still be matched, but neither is @@ -5054,7 +5122,7 @@ the head of former is a substitution instance of the latter. For example substituting a:=Int. -However, GHC is conservative about committing to an overlapping instance. For example: +GHC is conservative about committing to an overlapping instance. For example: f :: [b] -> [b] f x = ... @@ -5151,56 +5219,6 @@ the program prints would be to reject module Help on the grounds that a later instance declaration might overlap the local one.) - -The willingness to be overlapped or incoherent is a property of -the instance declaration itself, controlled by the -presence or otherwise of the -and flags when that module is -being defined. Suppose we are searching for an instance of the -target constraint (C ty1 .. tyn). -The search works like this. - - -Find all instances I that match the target constraint; -that is, the target constraint is a substitution instance of I. These -instance declarations are the candidates. - - - -Find all non-candidate instances -that unify with the target constraint. -Such non-candidates instances might match when the target constraint is further -instantiated. If all of them were compiled with -, proceed; if not, the search fails. - - - -Eliminate any candidate IX for which both of the following hold: - - -There is another candidate IY that is strictly more specific; -that is, IY is a substitution instance of IX but not vice versa. - -Either IX or IY was compiled with -. - - - - - - -If only one candidate remains, pick it. -Otherwise if all remaining candidates were compiled with -, pick an arbitrary candidate. - - - -These rules make it possible for a library author to design a library that relies on -overlapping instances without the library client having to know. - -The flag implies the - flag, but not vice versa. - -- cgit v1.2.1