But by doing so I am changing type equality to the same as having &quot;type family F a :: * -&gt; *&quot;<br><br>F&#39; a x ~ F&#39; b y &lt;=&gt; F&#39; a ~ F&#39; b /\ x ~ y (equality for ADTs)<br><br>&nbsp;and I would like this &quot;decomposition rule not to apply&quot; so.<br>
<br>Thanks though,<br>hugo<br><br><div class="gmail_quote">On Tue, Mar 18, 2008 at 1:12 AM, Ryan Ingram &lt;<a href="mailto:ryani.spam@gmail.com">ryani.spam@gmail.com</a>&gt; wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
On 3/17/08, Hugo Pacheco &lt;<a href="mailto:hpacheco@gmail.com">hpacheco@gmail.com</a>&gt; wrote:<br>
&gt; type family G a :: * -&gt; *<br>
&gt; type instance G Int = Either () -- you forgot this line<br>
<div class="Ih2E3d">&gt;<br>
&gt; instance Functor (G Int) where<br>
&gt; &nbsp; &nbsp;fmap f (Left ()) = Left ()<br>
&gt; &nbsp; &nbsp;fmap f (Right x) = Right (f x)<br>
<br>
</div>One thing that you don&#39;t seem to be clear about is that there is<br>
something slightly magic going on in this Functor definition; you are<br>
not declaring Functor (G Int) but rather Functor (whatever (G Int)<br>
turns into). &nbsp;This is using a GHC extension &quot;TypeSynonymInstances&quot;.<br>
The extension allows you to use type synonyms when declaring<br>
instances, but only if they are fully applied, and the compiler is<br>
simply applying the substitution for you.<br>
<br>
That is to say, this code is no different than the following:<br>
<br>
type family G a :: * -&gt; *<br>
type instance G Int = Either ()<br>
instance Functor (Either ()) where<br>
<div class="Ih2E3d"> &nbsp; &nbsp;fmap f (Left ()) = Left ()<br>
 &nbsp; &nbsp;fmap f (Right x) = Right (f x)<br>
<br>
</div>Once you declare a more complicated type function, such as<br>
<div class="Ih2E3d"> &nbsp; type family F a x :: *<br>
</div>this extension can no longer come into play.<br>
<br>
You can get around this restriction with a newtype:<br>
<div class="Ih2E3d"><br>
type family F a x :: *<br>
</div>type instance F Int x = Either () x<br>
<br>
newtype F&#39; a b = F&#39; (F a b)<br>
<br>
instance Functor (F&#39; Int) where<br>
 &nbsp; fmap f (F&#39; (Left ())) = F&#39; (Left ())<br>
 &nbsp; fmap f (F&#39; (Right x)) = F&#39; (Right $ f x)<br>
</blockquote></div><br>