<div dir="ltr">+1 to the original proposal and Edward&#39;s suggestion of emitting a warning.  I&#39;ve occasionally wanted this behavior from IncoherentInstances as well.<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Mon, Jul 29, 2013 at 3:01 PM, Edward Kmett <span dir="ltr">&lt;<a href="mailto:ekmett@gmail.com" target="_blank">ekmett@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I&#39;ll probably never use it, but I can&#39;t see any real problems with the proposal. In many ways it is what I always expected IncoherentInstances to be.<div><br></div><div>One thing you might consider is that if you have to make an arbitrary instance selection at the end during compile time, making that emit a warning by default or at least under -Wall. That way it is clear when you are leaning on underdetermined semantics.</div>
<span class="HOEnZb"><font color="#888888">
<div><br></div></font></span><div><span class="HOEnZb"><font color="#888888">-Edward</font></span><div><div class="h5"><br><br><div class="gmail_quote">On Sat, Jul 27, 2013 at 4:16 PM, Simon Peyton-Jones <span dir="ltr">&lt;<a href="mailto:simonpj@microsoft.com" target="_blank">simonpj@microsoft.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Friends<br>
<br>
I&#39;ve realised that GHC&#39;s -XIncoherentInstances flag is, I think, over-conservative.  I propose to liberalise it a bit. This email describes the issue.  Please yell if you think this is a bad idea.<br>
<br>
Simon<br>
<br>
Suppose we have<br>
<br>
        class C a where { op :: a -&gt; String }<br>
        instance C [a] where ...<br>
        instance C [Char] where ...<br>
<br>
        f :: [b] -&gt; String<br>
        f xs = &quot;Result:&quot; ++ op xs<br>
<br>
With -XOverlappingInstances, but without -XIncoherentInstances, f won&#39;t compile.  Reason: if we call &#39;f&#39; at Char (e.g.  f &quot;foo&quot;) then you might think we should use instance C [Char].  For example, if we inlined &#39;f&#39; at the call site, to get (&quot;Result:&quot; ++ op &quot;foo&quot;), we certainly then would use the C [Char] instance, giving perhaps different results.  If we accept the program as-is, we&#39;ll permanently commit &#39;f&#39; to using the C [a] instance.<br>


<br>
The -XIncoherentInstances flag says &quot;Go ahead and use an instance, even if another instance might become relevant if you were to specialise or inline the enclosing function.&quot;  The GHC user manual gives a more precise spec [1].<br>


<br>
Now consider this<br>
        class D a b where { opD :: a -&gt; b -&gt; String }<br>
        instance D Int b where ...<br>
        instance D a Int where ...<br>
<br>
        g (x::Int) = opD x x<br>
<br>
Here &#39;g&#39; gives rise to a constraint (D Int Int), and that matches two instance declarations.   So this is rejected regardless of flags.  We can fix it up by adding<br>
        instance D Int Int where ...<br>
but this is pretty tiresome in cases where it really doesn&#39;t matter which instance you choose.  (And I have a use-case where it&#39;s more than tiresome [2].)<br>
<br>
The underlying issue is similar to the previous example.  Before, there was *potentially* more than one way to generate evidence for (C [b]); here there is *actually* more than one instance.  In both cases the dynamic semantics of the language are potentially affected by the choice -- but -XIncoherentInstnaces says &quot;I don&#39;t care&quot;.<br>


<br>
<br>
So the change I propose to make IncoherentInstances to pick arbitrarily among instances that match.  More precisely, when trying to find an instance matching a target constraint (C tys),<br>
<br>
a) Find all instances matching (C tys); these are the candidates<br>
<br>
b) Eliminate any candidate X for which another candidate Y is<br>
  strictly more specific (ie Y is a substitution instance of X),<br>
  if either X or Y was complied with -XOverlappingInstances<br>
<br>
c) Check that any non-candidate instances that *unify* with (C tys)<br>
   were compiled with -XIncoherentInstances<br>
<br>
d) If only one candidate remains, pick it.<br>
    Otherwise if all remaining candidates were compiled with<br>
    -XInccoherentInstances, pick an arbitrary candidate<br>
<br>
All of this is precisely as now, except for the &quot;Otherwise&quot; part of (d).  One could imagine different flags for the test in (c) and (d) but I really don&#39;t think it&#39;s worth it.<br>
<br>
<br>
Incidentally, I think it&#39;d be an improvement to localise the Overlapping/Incoherent flags to particular instance declarations, via pragmas, something like<br>
        instance C [a] where<br>
          {-# ALLOW_OVERLAP #-}<br>
          op x = ....<br>
<br>
Similarly {-# ALLOW_INCOHERENT #-}.   Having -XOverlappingInstances for the whole module is a bit crude., and might be missed when looking at an instance.   How valuable would this be?<br>
<br>
[1] <a href="http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-overlap" target="_blank">http://www.haskell.org/ghc/docs/latest/html/users_guide/type-class-extensions.html#instance-overlap</a><br>


[2] <a href="http://ghc.haskell.org/trac/ghc/wiki/NewtypeWrappers" target="_blank">http://ghc.haskell.org/trac/ghc/wiki/NewtypeWrappers</a><br>
<br>
<br>
<br>
_______________________________________________<br>
Glasgow-haskell-users mailing list<br>
<a href="mailto:Glasgow-haskell-users@haskell.org" target="_blank">Glasgow-haskell-users@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/glasgow-haskell-users" target="_blank">http://www.haskell.org/mailman/listinfo/glasgow-haskell-users</a><br>
</blockquote></div><br></div></div></div>
<br>_______________________________________________<br>
Glasgow-haskell-users mailing list<br>
<a href="mailto:Glasgow-haskell-users@haskell.org">Glasgow-haskell-users@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/glasgow-haskell-users" target="_blank">http://www.haskell.org/mailman/listinfo/glasgow-haskell-users</a><br>
<br></blockquote></div><br></div>