<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
p.Code, li.Code, div.Code
        {mso-style-name:Code;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:22.7pt;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";
        font-weight:bold;}
p.msonormal0, li.msonormal0, div.msonormal0
        {mso-style-name:msonormal;
        mso-margin-top-alt:auto;
        margin-right:0cm;
        mso-margin-bottom-alt:auto;
        margin-left:0cm;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;
        mso-fareast-language:EN-US;}
.MsoPapDefault
        {mso-style-type:export-only;
        margin-top:6.0pt;
        margin-right:0cm;
        margin-bottom:6.0pt;
        margin-left:0cm;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:885410172;
        mso-list-type:hybrid;
        mso-list-template-ids:1314684040 -345845632 134807577 134807579 134807567 134807577 134807579 134807567 134807577 134807579;}
@list l0:level1
        {mso-level-number-format:alpha-upper;
        mso-level-text:"\(%1\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:54.0pt;
        text-indent:-18.0pt;}
@list l0:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:90.0pt;
        text-indent:-18.0pt;}
@list l0:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:126.0pt;
        text-indent:-9.0pt;}
@list l0:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:162.0pt;
        text-indent:-18.0pt;}
@list l0:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:198.0pt;
        text-indent:-18.0pt;}
@list l0:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:234.0pt;
        text-indent:-9.0pt;}
@list l0:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:270.0pt;
        text-indent:-18.0pt;}
@list l0:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        margin-left:306.0pt;
        text-indent:-18.0pt;}
@list l0:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        margin-left:342.0pt;
        text-indent:-9.0pt;}
@list l1
        {mso-list-id:1113280310;
        mso-list-type:hybrid;
        mso-list-template-ids:-1849781886 134807553 134807555 134807557 134807553 134807555 134807557 134807553 134807555 134807557;}
@list l1:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Symbol;}
@list l1:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:"Courier New";}
@list l1:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Wingdings;}
@list l1:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Symbol;}
@list l1:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:"Courier New";}
@list l1:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Wingdings;}
@list l1:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Symbol;}
@list l1:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:"Courier New";}
@list l1:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;
        font-family:Wingdings;}
ol
        {margin-bottom:0cm;}
ul
        {margin-bottom:0cm;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-GB" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Let me have a quick stab at Nick’s idea.   Consider<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">               forall b[2]. (a ~ Int) => alpha[1] ~ Maybe a<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Then we don’t want to unify alpha := Maybe a, because an equally good way to solve the constraint would be alpha := Maybe Int.  And constraints elsewhere might force one or the other to be the “right”
 one.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">But suppose none of the given constraints involve ‘a’ in any way, shape, or form.  For example:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">               forall b[2]. (b ~ Int) => alpha[1] ~ Maybe a<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Well then, we have no local constraints on a, so we can’t get any ambiguity. Aha – this is covered by the current “local equalities” story.  Note [Let-bound skolems] in TcSMonad.  
<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">But what about this:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">               forall b[2]. (F b ~ G b) => alpha[1] ~ Maybe a<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">That is *<b>not</b>* covered by the current local-equalities story, but I think is equally immune to producing a local constraint on ‘a’.  And Iavor’s example is just such a case.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">So here is a possible refinement:<o:p></o:p></span></p>
<ol style="margin-top:0cm" start="1" type="A">
<li class="MsoListParagraph" style="margin-left:18.0pt;mso-list:l0 level1 lfo2"><span style="mso-fareast-language:EN-US">An implication is considered to “bind local equalities” iff it has at least one given equality whose free variables are not all bound by
 the same implication.<o:p></o:p></span></li></ol>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">That loosens up Note [Let-bound skolems] in TcSMonad, perhaps significantly.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Could we go further?<o:p></o:p></span></p>
<ol style="margin-top:0cm" start="2" type="A">
<li class="MsoListParagraph" style="margin-left:18.0pt;mso-list:l0 level1 lfo2"><span style="mso-fareast-language:EN-US">An equality (t1~t2) can float out of an implication (forall as. C => blah) iff, assuming fvs(t1,t2) = FV<o:p></o:p></span></li><ol style="margin-top:0cm" start="1" type="a">
<li class="MsoListParagraph" style="margin-left:18.0pt;mso-list:l0 level2 lfo2"><span style="mso-fareast-language:EN-US">The ‘as’ are disjoint from FV obviously.<o:p></o:p></span></li><li class="MsoListParagraph" style="margin-left:18.0pt;mso-list:l0 level2 lfo2"><span style="mso-fareast-language:EN-US">None of the equality constraints in C mentions any of the variables in FV<o:p></o:p></span></li></ol>
</ol>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">This is a bit looser because in<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">               forall c[2]. (b ~ Int) => alpha[1] ~ a<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">it would allow the equality alpha~a to float even though there is a real local equality (b~Int).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">I’m a bit worried about (B) however.  Suppose we had a Given equality (a ~ b).  Then suddenly that local Given (b ~ Int) does actually constrain a after all.  Can we have Givens we didn’t “see” before? 
 Yes, via superclasses or outer unifications.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">So I would be rather cautious about (B).  But (A) looks sound to me.  I think it would address Iavor’s example, but perhaps not Nick’s.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US">Simon<o:p></o:p></span></p>
<p class="MsoNormal"><span style="mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt">
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal"><b><span lang="EN-US">From:</span></b><span lang="EN-US"> ghc-devs <ghc-devs-bounces@haskell.org>
<b>On Behalf Of </b>Nicolas Frisby<br>
<b>Sent:</b> 21 May 2019 00:58<br>
<b>To:</b> Iavor S. S. Diatchki <iavor.diatchki@gmail.com><br>
<b>Cc:</b> ghc-devs@haskell.org; Ryan Scott <ryan.gl.scott@gmail.com><br>
<b>Subject:</b> Re: Bug or feature?<o:p></o:p></span></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Also, thanks for the concrete counter example! I tried to organize my thoughts on this kind of thing a while ago (see rambly notes at
<a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.haskell.org%2Fghc%2Fghc%2Fwikis%2Ffloat-more-eqs2018&data=02%7C01%7Csimonpj%40microsoft.com%7C8541805315cb456e1eef08d6dd7f00c0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636939934881644934&sdata=usdD49rcTG38IxnbKbH5veEodq%2BcHhBmjw19y5SWzUQ%3D&reserved=0">
https://gitlab.haskell.org/ghc/ghc/wikis/float-more-eqs2018</a> and my comments on #15009), but didn't succeed before setting it aside. Your counter example is very helpful as a conversation substrate.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<span style="font-family:"Arial",sans-serif">Disclaimer: I've only ever tested my understanding of this stuff with GHC itself (as a typechecker plugin author, with a malnourished test suite to boot), so I'm not totally confident in what follows. Excited for
 others to review.</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Iavor's user decl:<o:p></o:p></p>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<span style="font-size:9.5pt;font-family:"Arial",sans-serif;color:purple">    data Q3 = forall a. Q3 (forall b. (F b ~ Int) => T a b)</span><o:p></o:p></p>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<span style="font-family:"Arial",sans-serif"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<span style="font-family:"Arial",sans-serif">Your summary of the relevant Wanted implication of the ambiguity check:<o:p></o:p></span></p>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<br>
<span style="font-size:9.5pt;font-family:"Arial",sans-serif;color:purple">   forall a. forall b. (F b ~ Int) => (a ~ alpha)</span><o:p></o:p></p>
</div>
</div>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Your explanation of the "counter-example" due to the open world assumption:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<span style="font-size:9.5pt;font-family:"Arial",sans-serif">type family G i a<br>
    type instance G Int a = a<br>
<br>
If that were the case, then the implication constraint above would no<br>
longer have a unique solution, since there would exist another<br>
substitution [alpha |-> G (F b) a] that is incomparable with [alpha<br>
|-> a]. OutsideIn(X) was designed to only pick unique solutions …</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
If we write the Wanted again with explicit tyvar levels:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
    forall a[1]. forall b[2]. (F b ~ Int) => (a ~ alpha[2])<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
And flatten:<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<span style="font-family:"Arial",sans-serif">    forall a[1]. forall b[2]. (F b ~ fsk[2], fsk ~ Int) => (a ~ alpha[1])</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<span style="font-family:"Arial",sans-serif">Then I think your counter example becomes:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
    the substitution mapping alpha[1] to G fsk[2] a[1]<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
(I'm eliding the corresponding fmv flatten skolem; irrelevant, I think.)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
But that mapping is "ill-leveled", isn't it? The level 2 skolem b[2] would be escaping if a type including it were assigned to the level 1 univar alpha[1]. (I'm unsure if b's position as an argument to a tyfam <span style="font-family:"Arial",sans-serif">in
 the RHS of alpha</span> matters -- my intuition says it does not.)<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Could be an exciting improvement to unification under local equalities, if I'm right here and also the argument generalizes beyond this kind of example.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Please let me know what you think! Thanks. -Nick<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
On Mon, May 20, 2019, 16:26 Nicolas Frisby <<a href="mailto:nicolas.frisby@gmail.com" target="_blank">nicolas.frisby@gmail.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
FYI, your Q2 (with no tyfam) is well-typed because of #15009<o:p></o:p></p>
</div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
<o:p> </o:p></p>
<div>
<div>
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
On Mon, May 20, 2019, 11:01 Iavor Diatchki <<a href="mailto:iavor.diatchki@gmail.com" target="_blank">iavor.diatchki@gmail.com</a>> wrote:<o:p></o:p></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0cm 0cm 0cm 6.0pt;margin-left:4.8pt;margin-right:0cm">
<p class="MsoNormal" style="mso-margin-top-alt:6.0pt;margin-right:0cm;margin-bottom:6.0pt;margin-left:0cm">
Hi,<br>
<br>
thanks for the detailed response---I thought something like that might<br>
be happening, which is why I thought I'd better ask before reporting a<br>
bug.<br>
<br>
I wonder how we might make the error message a little more user<br>
friendly.   One idea would be to compute a couple of examples to show,<br>
after an ambiguity check fails.<br>
<br>
-Iavor<br>
<br>
On Sat, May 18, 2019 at 7:03 AM Ryan Scott <<a href="mailto:ryan.gl.scott@gmail.com" target="_blank">ryan.gl.scott@gmail.com</a>> wrote:<br>
><br>
> Hi Iavor,<br>
><br>
> This is a feature in the sense that it is an expected outcome of the<br>
> OutsideIn(X) type inference algorithm (in particular, Section 5 of the<br>
> corresponding paper [1]). I'll try to explain the issue to the best of<br>
> my understanding.<br>
><br>
> The tricky thing about the Q3 data type:<br>
><br>
>     data Q3 = forall a. Q3 (forall b. (F b ~ Int) => T a b)<br>
><br>
> Is that there is a rank-n type with a /local/ equality constraint. In<br>
> order to ensure that the type of the Q3 data constructor is never<br>
> ambiguous, GHC tries to infer that Q3's type is always a subtype of<br>
> itself. As a part of this, GHC attempts to solve the following<br>
> implication constraint:<br>
><br>
>     forall a. forall b. (F b ~ Int) => (a ~ alpha)<br>
><br>
> Where `alpha` is a unification variable. GHC tries to find a unique,<br>
> most-general substitution that solves this constraint but ultimately<br>
> gives up and reports the "untouchable" error message you observed.<br>
><br>
> This is a bit strange, however. Upon first glance, this constraint<br>
> would appear to have a unique solution: namely, [alpha |-> a]. Why<br>
> doesn't GHC just use this? Ultimately, it's because OutsideIn(X) is<br>
> conservative: there may exist constraints that admit a unique solution<br>
> which it may fail to solve. This is explained in greater depth in<br>
> Section 5.2 of the paper, but the essence of this restriction is<br>
> because of the open-world assumption for type families. Namely, it's<br>
> possible that your Q3 data type might later be linked against code<br>
> which defines the following type family:<br>
><br>
>     type family G i a<br>
>     type instance G Int a = a<br>
><br>
> If that were the case, then the implication constraint above would no<br>
> longer have a unique solution, since there would exist another<br>
> substitution [alpha |-> G (F b) a] that is incomparable with [alpha<br>
> |-> a]. OutsideIn(X) was designed to only pick unique solutions that<br>
> remain unique solutions even if more axioms (i.e., type family<br>
> equations) are added, so for these reasons it fails to solve the<br>
> implication constraint above.<br>
><br>
> See also GHC issues #10651 [2], #14921 [3], and #15649 [4], which all<br>
> involve similar issues.<br>
><br>
> -----<br>
><br>
> I'm far from an expert on type inference, so I can't really offer a<br>
> better inference algorithm that would avoid this problem. The best you<br>
> can do, as far as I can tell, is to enable AllowAmbiguousTypes and<br>
> hope for the best. Even then, you'll still run into situations where<br>
> untouchability rears its ugly head, as in your `q3` definition. When<br>
> that happens, your only available option (again, as far as I can tell)<br>
> is to make use of TypeApplications. For example, the following /does/<br>
> typecheck:<br>
><br>
>     q3 :: Q3<br>
>     q3 = Q3 @Bool t<br>
><br>
> Hope that helps,<br>
><br>
> Ryan S.<br>
> -----<br>
> [1] <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.microsoft.com%2Fen-us%2Fresearch%2Fwp-content%2Fuploads%2F2016%2F02%2Fjfp-outsidein.pdf&data=02%7C01%7Csimonpj%40microsoft.com%7C8541805315cb456e1eef08d6dd7f00c0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636939934881644934&sdata=tLMnhJGSfmhl5ENnluDF1A7xSy9JBaAMTN9tMFVPvVU%3D&reserved=0" target="_blank">
https://www.microsoft.com/en-us/research/wp-content/uploads/2016/02/jfp-outsidein.pdf</a><br>
> [2] <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.haskell.org%2Fghc%2Fghc%2Fissues%2F10651&data=02%7C01%7Csimonpj%40microsoft.com%7C8541805315cb456e1eef08d6dd7f00c0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636939934881654927&sdata=4k3SxYqoriadeXMvOf2AsWIPJHfOATzIAzDOmRxodAA%3D&reserved=0" target="_blank">
https://gitlab.haskell.org/ghc/ghc/issues/10651</a><br>
> [3] <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.haskell.org%2Fghc%2Fghc%2Fissues%2F14921&data=02%7C01%7Csimonpj%40microsoft.com%7C8541805315cb456e1eef08d6dd7f00c0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636939934881654927&sdata=z8or8qyebl7pTm4zbxe8ZYM6%2FFRwoAST0v27kh0IMy4%3D&reserved=0" target="_blank">
https://gitlab.haskell.org/ghc/ghc/issues/14921</a><br>
> [4] <a href="https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.haskell.org%2Fghc%2Fghc%2Fissues%2F15649&data=02%7C01%7Csimonpj%40microsoft.com%7C8541805315cb456e1eef08d6dd7f00c0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636939934881654927&sdata=GER2%2BvIIMNCyQmlSohkkZxV9PdbMX9QLV1PL7a8tMzc%3D&reserved=0" target="_blank">
https://gitlab.haskell.org/ghc/ghc/issues/15649</a><br>
> _______________________________________________<br>
> ghc-devs mailing list<br>
> <a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
> <a href="https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-devs&data=02%7C01%7Csimonpj%40microsoft.com%7C8541805315cb456e1eef08d6dd7f00c0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636939934881664921&sdata=vafMrsPPVbBzZeTLYPREXBgfclzb9yYbE29SFqIB99k%3D&reserved=0" target="_blank">
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><br>
_______________________________________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org" target="_blank">ghc-devs@haskell.org</a><br>
<a href="https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-devs&data=02%7C01%7Csimonpj%40microsoft.com%7C8541805315cb456e1eef08d6dd7f00c0%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636939934881664921&sdata=vafMrsPPVbBzZeTLYPREXBgfclzb9yYbE29SFqIB99k%3D&reserved=0" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs</a><o:p></o:p></p>
</blockquote>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</body>
</html>