<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>