<div dir="ltr">I've been thinking about this a bit more - I'm still not sure if it's correct for the instance above to require UndecidableInstances.<div><br></div><div>Why is the `a` counting towards the "size" of the constraint? It seems like since it's introduced existentially, it shouldn't introduce ambiguities in the typeclass resolution mechanism. However, I know little about the internals of the typeclass solver, so I could be wrong about that. </div><div><br></div><div></div></div><br><div class="gmail_quote"><div dir="ltr">On Sat, Dec 15, 2018 at 8:58 PM William Yager <<a href="mailto:will.yager@gmail.com">will.yager@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr">There may be some fun to be had with QuantifiedConstraints. I've thought about solving similar parser/formatter problems this way, extending parsers via functor composition. Consider:<div><br></div><div><p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">> data F f = F (f (F f))</span></p><p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">> -- Sadly the below does not work. It seems like maybe it should be able to work?</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">> instance (forall a . Show a => Show (f a)) => Show (F f) where show (F f) = "(F " ++ show f ++ ")"</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0);min-height:13px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures"><interactive>:23:10: </span><span style="font-variant-ligatures:no-common-ligatures;color:rgb(195,55,32)">error:</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">    • The constraint ‘Show (f a)’</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">        is no smaller than the instance head ‘Show (F f)’</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">      (Use UndecidableInstances to permit this)</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">    • In the instance declaration for ‘Show (F f)’</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)">> -- We can get something almost as good</p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">> class (forall a . Show a => Show (f a)) => Show1 f</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">> instance Show1 f => Show (F f) where show (F f) = "(F " ++ show f ++ ")"</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">> instance Show1 Maybe</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">> show (F $ Just $ F $ Nothing)</span></p>
<p style="margin:0px;font-stretch:normal;font-size:11px;line-height:normal;font-family:"Fira Code";color:rgb(0,0,0)"><span style="font-variant-ligatures:no-common-ligatures">"(F Just (F Nothing))"</span></p></div><div><span style="font-variant-ligatures:no-common-ligatures"><br></span></div><div><span style="font-variant-ligatures:no-common-ligatures"><br></span></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Dec 14, 2018 at 10:52 PM MarLinn <<a href="mailto:monkleyon@gmail.com" target="_blank">monkleyon@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF">
    <p>Hi Ducis,<br>
    </p>
    <p>you can parametrise over type variables of other kinds than just
      *.</p>
    <p>If what you write is really what you want, the most
      straightforward answer is simply</p>
    <pre> data ExprG f
            = Var      VarName
            | Enclosed VarName (f Expr) VarName
            | Prefix   (f Expr) (f Expr)
            | Ternary  (f Expr) VarName (f Expr) VarName (f Expr)
        
        type Expr  = ExprG Identity -- From Data.Functor.Identity
        type ExprL = ExprG []
        type ExprD = ExprG DList</pre>
    <p>There is no mention of the word "functor" because you will have
      to add that constraint to the usage sites.</p>
    <p>Downside: notice that the deriving clauses are gone because the
      instances aren't as easy to derive any more. Even the simplest and
      most harmless way I know to get that possibility back involves two
      language extensions: <tt>StandaloneDeriving</tt> and <tt>FlexibleInstances</tt>.
      With those you can write</p>
    <pre> deriving instance Show (ExprG Identity)
        deriving instance Show (ExprG [])
        deriving instance Show (ExprG DList)
        deriving instance Eq   (ExprG Identity)
        :</pre>
    <p>I suspect though that what you actually want, but didn't write,
      is more along the lines of</p>
    <pre> data ExprL = … | EnclosedL VarName [ExprL]       VarName | …   -- using ExprL instead of Expr on the right side

        data ExprD = … | EnclosedD VarName (DList ExprD) VarName | …   -- using ExprD instead of Expr on the right side
</pre>
    <p>The good news is that if you have the first solution, this step
      is rather simple. Because you can just use replace <tt>Expr</tt>
      with <tt>ExprG f</tt> again:<br>
    </p>
    <pre> data ExprG f
            = Var      VarName
            | Enclosed VarName (f (ExprG f)) VarName
            | Prefix   (f (ExprG f)) (f (ExprG f))
            | Ternary  (f (ExprG f)) VarName (f (ExprG f)) VarName (f (ExprG f))</pre>
    <p>The better news is that although this looks repetitive and hard
      to read, it's well on the way to discovering the magic of the Free
      Monad.</p>
    <p>Hope this helps.<br>
    </p>
    <p>Cheers,<br>
      MarLinn<br>
    </p>
    <p><br>
    </p>
  </div>

_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div>
</div>
</blockquote></div>