<div dir="ltr"><div dir="ltr">> <span style="color:rgb(0,0,0);white-space:pre-wrap">A precondition is that it scans instances in </span><span style="color:rgb(0,0,0);white-space:pre-wrap">most-specific-first sequence</span><div><span style="color:rgb(0,0,0);white-space:pre-wrap">> -- which Hugs is already doing.</span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap"><br></span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">It galled me that going only by (an adapted notion of) overlap, I still had to write three instances for a three-FunDep AddNat:</span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap"><br></span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">>    class AddNat x y z  | x y -> z, x z -> y, y z -> x</span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">></span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">>    instance</span>

<span style="color:rgb(0,0,0);white-space:pre-wrap">                 </span><span style="color:rgb(0,0,0);white-space:pre-wrap">AddNat Z     Z      Z     </span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">>    instance                  AddNat Z      (S y') (S y')</span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">></span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">>    instance AddNat x' y z' => AddNat (S x') y     (S z')</span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">></span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap"><br></span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">because the 'obvious' way to write, with two instances (see below), put them in no substitution ordering for the argument positions to the third FunDep. So I dug out an idea from a few years ago (rejected proposal) and implemented:</span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap"><br></span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">>    </span><span style="color:rgb(0,0,0);white-space:pre-wrap">instance</span> <span style="color:rgb(0,0,0);white-space:pre-wrap">                 </span><span style="color:rgb(0,0,0);white-space:pre-wrap">AddNat Z     y      y    </span></div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">></span></div><div><div><span style="color:rgb(0,0,0);white-space:pre-wrap">>    instance AddNat x' y z' => AddNat (S x') y     (S z')  | y /~ (S z')</span></div>></div><div><br></div><div>That after the `|` in the instance is an 'Instance Disequality Guard': prefer a more specific instance if those two types from the head unify.</div><div><br></div><div>Then Hugs puts that instance later in the preference ordering than the first instance -- because the instance heads unify going by the argument positions, but the first instance has no guard.</div><div><br></div><div>This also works for the semi-overlap instances that Hugs currently rejects/GHC accepts but might turn out to be unusable:</div><div><br></div><div>>    class Semi a b</div><div>></div><div>>    instance Semi Int b</div><div>>    instance Semi a   Bool  | a /~ Int</div><div>></div><div>>    [W] Semi Int Bool             -- GHC currently rejects as ambiguous</div><div><br></div><div>The guard says: in case of [W] Semi Int Bool, prefer the Semi Int b instance. We can even go:</div><div><br></div><div>>    instance Semi Int Bool</div><div>></div><div>>    instance Semi Int b     | b /~ Bool</div><div>>    instance Semi a   Bool  | a /~ Int</div><div>></div><div>>    instance Semi a  b             -- no guard, because strictly more general than any instance</div><div><br></div><div><br></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
</blockquote></div></div>