<div dir="auto"><div dir="auto">To avoid actually realizing those boring fields in memory, use an unlifted newtype.</div><div dir="auto"><br></div><div dir="auto">type VoidUnit# :: TYPE ('TupleRep '[])</div><div dir="auto">newtype VoidUnit# = VoidUnit# VoidUnit#</div><div dir="auto"><br></div><div dir="auto">absurd# :: VoidUnit# -> a</div><div dir="auto">absurd# (VoidUnit# v) = absurd# v</div><div dir="auto"><br></div><div dir="auto">Unfortunately, GHC's pattern checker isn't smart enough to see by itself that VoidUnit# is uninhabited, even though that's pretty obvious to a human.</div><div dir="auto"><br></div>TTG also has coercion problems thanks to the type families. *Sigh*<br><br><div class="gmail_quote" dir="auto"><div dir="ltr" class="gmail_attr">On Wed, Aug 31, 2022, 4:48 PM Olaf Klinke <<a href="mailto:olf@aatal-apotheke.de">olf@aatal-apotheke.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> Trees that grow is essentially this, but using type families.<br>
> <br>
>     data Foo ksi<br>
>         = LeftFoo !(XLeftFoo ksi) !A<br>
>         | RightFoo !(XRightFoo ksi) !B<br>
> <br>
>     type family XLeftFoo ksi :: Type<br>
>     type family XRightFoo ksi :: Type<br>
> <br>
> Then you can define<br>
> <br>
>     data Both<br>
>     type instance XLeftFoo  Both = ()<br>
>     type instance XRightFoo Both = ()<br>
> <br>
> or<br>
> <br>
>     data OnlyLeft<br>
>     type instance XLeftFoo  OnlyLeft = ()<br>
>     type instance XRightFoo OnlyLeft = Void<br>
> <br>
> ---<br>
> <br>
> Third option is to simply have parametrized data:<br>
> <br>
>    data Foo b<br>
>        = LeftFoo !A<br>
>        | RIghtFoo !b<br>
> <br>
>    type FooBoth = Foo B<br>
>    type FooOnlyLeft = Foo Void<br>
> <br>
> ---<br>
> <br>
> Sometimes I prefer a higher-kinded data approach, especially if there is<br>
> very little variants needed, and they are "uniform" (e.g. second variant<br>
> doesn't have some fields).<br>
> Yet, sometimes simple parameterized data is simplest approach<br>
> (especially as you get stuff for free by deriving Traversable!).<br>
> <br>
> On the other hand, if type is big and have many uniform extension points<br>
> (even if there are few different combinations), then HKD becomes<br>
> boilerplate heavy as well.<br>
> The drawback of TTG, is that writing polymorphic code (i.e. which work<br>
> for any or some `ksi`s) is not very fun: a lot of equality constraints etc.<br>
> <br>
> - Oleg<br>
<br>
So I re-discovered Trees that Grow sans the trick of using type<br>
families to name particular combinations of parameters. Hooray Najd,<br>
and thanks Oleg for bringing this up. <br>
<br>
Olaf<br>
<br>
_______________________________________________<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 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>