Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimal superset of two Coproducts? #198

Closed
rosefromthedead opened this issue Aug 22, 2022 · 2 comments
Closed

Minimal superset of two Coproducts? #198

rosefromthedead opened this issue Aug 22, 2022 · 2 comments

Comments

@rosefromthedead
Copy link
Contributor

In my library, I have a generic function that creates a superset of two coproducts, which come from its type arguments. Currently I'm using two CoproductEmbedder bounds, but since there are infinite coproduct types that satisfy any set of Embedder bounds, type inference fails, and users of the library have to specify the superset type themselves. This is bad on its own, but the function has 22 generic arguments, so the user ends up with quite a few underscores.

So, how can I get the compiler to infer the minimal superset (I suppose the union?) of some coproducts? I've been trying to make a new CoproductJoiner trait to help, but so far I've failed, and I suppose the maintainers here are likely better at this sort of thing than I am :D

@ExpHP
Copy link
Collaborator

ExpHP commented Aug 22, 2022

If you're only ever using this with completely disjoint sets of types, this should be possible.

However, I presume you included the word "minimal" for a reason... and unfortunately, any attempt to join two coproducts without duplicates smells impossible. By which I mean, it sounds similar to numerous other things that have previously been found to be impossible to implement in frunk due to limitations of rust's trait system.

In particular:

  • If you want CoproductJoiner<Coprod![B]> for Coprod![A] to produce Coprod![A, B],
  • ...but also want CoproductJoiner<Coprod![A]> for Coprod![A] to produce Coprod![A],

then almost certainly, any attempt to make the first bullet work for most B will have parametricity over B, causing it to apply to all B, including B=A; which will conflict with the second bullet. Frunk's use of index types to disambiguate impls does allow it to overcome some problems of overlapping impls, but even this technique cannot be used to break parametricity.


22 generic arguments

Ahh-e-uh. Yikes!

I don't really have a nice alternative to recommend here.

Depending on your circumstances, perhaps one possible compromise is to use a single superset coproduct type throughout the higher-level parts of the application, to reduce the number of places where distinct type annotations must be maintained. (however, this also forfeits many of the benefits of Coproduct, and at some point one must ask themselves if they'd be better off with a regular enum).

Another possibility is that, if the simpler form of CoproductJoiner were added (one which just concatenates the coproducts, e.g. Coprod![A, B] | Coprod![A, C] == Coprod![A, B, A, C]), then maybe you could use that, and then at some point waaaaay down the line, you could convert your hastily-constructed Coprod![A, B, A, A, C, D, A, B, A, E, F, A] into a cleaner Coprod![A, B, C, D, E, F].

@rosefromthedead
Copy link
Contributor Author

rosefromthedead commented Aug 22, 2022

Thanks for the help. As it stands I don't think what I want is possible in Rust today. Honestly I'll probably just make a macro to allow the user to specify the type without also specifying the 21 underscores...

Yikes!

Understandable, but it's for a good cause.. eh.. I think. 9 of the arguments are frunk indices :P

It's possible that the concatenation idea might lead to something, but my intuition is that it won't, because I need to be able to embed the subsets in the superset without knowing the superset concretely. As far as I can see that's not possible without indices, which can't be inferred (or don't make sense) unless there are no duplicates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants