<div dir="ltr">> I figured out that this compiles:<br>> <br>> data HKD (f :: Type -> Type) = Foo (F1 Int f) (F1 Double f)<br>> | Bar (F1 Bool f)<br>> deriving Generic1<br>> <br>> newtype F1 a f = F1 { unF1 :: f a }<br><br>Yes, that's a useful trick to keep in mind. For what it's worth, I think your `F1` is the same thing as `Barbie` [1] from the `barbies` library.<br><br>> Would it be a good idea to add F1 to GHC.Generics?<br><br>There's a couple of issues that make me cautious about this idea:<br><br>1. This isn't an issue that's specific to `DeriveGeneric`. Other `stock` deriving strategies that deal with similar classes, such as `DeriveFunctor`, also suffer from this problem. For instance, you can't do the following:<br><br> > data T a = MkT (Either a Int) deriving Functor<br><br> Again, the issue is that the last type parameter (`a`) appears in a field type in a position other than as the last argument. To make _this_ work, you'd need something like `Flip` [2] from the `bifunctors` library:<br> <br> > data T a = MkT (Flip Either Int a) deriving Functor<br> <br> That leads into the second issue...<br>2. There are an infinite number of different type variable combinations you could conceivably add special support for. I've already mentioned `Barbie` and `Flip` above, but you could just as well put the last type parameter in other places as well:<br><br> > data S1 a = MkS1 (a, Int, Int) deriving Generic1<br> > data S2 a = MkS2 (a, Int, Int, Int) deriving Generic1<br> > data S3 a = MkS3 (a, Int, Int, Int, Int) deriving Generic1<br> > ...<br> <br> And this is only if you assume that the last type parameter only appears once in each field type. You'd need even more special cases if the last type parameter appears in multiple places in a field type:<br> <br> > data U1 a = MkU1 (a, a) deriving Generic1<br> > data U2 a = MkU2 (a, a, a) deriving Generic1<br> > ...<br> <br> With all of these possibilities, it's difficult to say how far we should go with this.<br> <br>Generally speaking, my recommendation for people who are dissatisfied with `Generic1`'s restrictions on where the last type parameter can be placed is to not use `Generic1` at all. There are other generic programming libraries that do not have the same restrictions, such as `kind-generics` [3]. Using something like `kind-generics` avoids the need to use things like `Barbie`, `Flip`, etc. in the first place.<br> <br>Best,<br><br>Ryan<br>-----<br>[1] <a href="https://hackage.haskell.org/package/barbies-2.0.3.0/docs/Barbies.html#t:Barbie">https://hackage.haskell.org/package/barbies-2.0.3.0/docs/Barbies.html#t:Barbie</a><br>[2] <a href="https://hackage.haskell.org/package/bifunctors-5.5.11/docs/Data-Bifunctor-Flip.html#t:Flip">https://hackage.haskell.org/package/bifunctors-5.5.11/docs/Data-Bifunctor-Flip.html#t:Flip</a><br><div>[3] <a href="https://hackage.haskell.org/package/kind-generics">https://hackage.haskell.org/package/kind-generics</a></div><div><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Oct 13, 2021 at 9:26 AM Fumiaki Kinoshita <<a href="mailto:fumiexcel@gmail.com" target="_blank">fumiexcel@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">Oh, I drew a conclusion too early when fiddling with a hypothetical Generic1 instance. I now think it's not possible to define an instance with the current kit.</div><div dir="ltr"><br></div><div dir="ltr">I figured out that this compiles:</div><div dir="ltr"><br></div><div dir="ltr">
<div style="color:rgb(212,212,212);background-color:rgb(30,30,30);font-family:Consolas,"Courier New",monospace;font-weight:normal;font-size:14px;line-height:19px;white-space:pre-wrap"><div><span style="color:rgb(86,156,214)">data</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">HKD</span><span style="color:rgb(212,212,212)"> (</span><span style="color:rgb(156,220,254)">f</span><span style="color:rgb(212,212,212)"> :: </span><span style="color:rgb(86,156,214)">Type</span><span style="color:rgb(212,212,212)"> -> </span><span style="color:rgb(86,156,214)">Type</span><span style="color:rgb(212,212,212)">) = Foo (</span><span style="color:rgb(86,156,214)">F1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Int</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(156,220,254)">f</span><span style="color:rgb(212,212,212)">) (</span><span style="color:rgb(86,156,214)">F1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Double</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(156,220,254)">f</span><span style="color:rgb(212,212,212)">)</span></div><div><span style="color:rgb(212,212,212)"> | Bar (</span><span style="color:rgb(86,156,214)">F1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Bool</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(156,220,254)">f</span><span style="color:rgb(212,212,212)">)</span></div><div><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">deriving</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Generic1</span></div><br><div><span style="color:rgb(86,156,214)">newtype</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">F1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(156,220,254)">a</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(156,220,254)">f</span><span style="color:rgb(212,212,212)"> = F1 { </span><span style="color:rgb(156,220,254)">unF1</span><span style="color:rgb(212,212,212)"> :: </span><span style="color:rgb(156,220,254)">f</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(156,220,254)">a</span><span style="color:rgb(212,212,212)"> }</span></div></div>
</div><div dir="ltr"><br></div><div>Problem solved, thanks!</div><div><br></div><div>Would it be a good idea to add F1 to GHC.Generics? Omitting metadata, it'd derive something like<br></div><div><br></div><div>
<div style="color:rgb(212,212,212);background-color:rgb(30,30,30);font-family:Consolas,"Courier New",monospace;font-weight:normal;font-size:14px;line-height:19px;white-space:pre-wrap"><div><span style="color:rgb(86,156,214)">instance</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Generic1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">HKD</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">where</span></div><div><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">type</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Rep1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">HKD</span><span style="color:rgb(212,212,212)"> = </span><span style="color:rgb(86,156,214)">F1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Int</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">:*:</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">F1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Double</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">:+:</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">F1</span><span style="color:rgb(212,212,212)"> </span><span style="color:rgb(86,156,214)">Bool</span></div><div><span style="color:rgb(212,212,212)"> from1 (Foo a b) = L1 (F1 a :*: F1 b)</span></div><div><span style="color:rgb(212,212,212)"> from1 (Bar c) = R1 (F1 c)</span></div><div><span style="color:rgb(212,212,212)"> to1 (L1 (F1 a :*: F1 b)) = Foo a b</span></div><div><span style="color:rgb(212,212,212)"> to1 (R1 (F1 c)) = Bar c</span></div></div>
</div><div dir="ltr"><br></div><div>I suppose it doesn't affect existing Generic1 instances and uses, so I don't expect breakages by adding this<br></div><br><div class="gmail_quote">...</div></div>
</blockquote></div></div>