-
Notifications
You must be signed in to change notification settings - Fork 83
[Proposal/RFC] Encoding partially applied functions #538
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
base: main
Are you sure you want to change the base?
Conversation
CodSpeed Performance ReportMerging #538 will not alter performanceComparing Summary
|
|
|
||
| # Known limitations | ||
|
|
||
| - Primitive outputs have to be wrapped in a constructor, which can be inconvenient |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think primitive inputs need to be wrapped as well (e.g., how to represent NumOp in your example below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right, that's true
(unless we generate specialized PartialApp operators for each type instead of type erasure)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am anti type erasure, but it think it is needed to support nested PartialApps as in the last example.
|
I see two different end goals for higher-order functions in egglog:
This proposal moves us towards Option 1. However, I also think that Option 2 is worth considering, and hasn't been discussed much. In particular, I think @FTRobbin has some thoughts on how One upside of Option 1 is that it can be done entirely in (There is also of course the secret Option 3: we declare that higher-order functions are out-of-scope, and force users to do Option 1 themselves if they really think they want it.) |
|
I didn't realize that others weren't thinking about this difference; when I was saying that it was impossible to implement UnstableFn purely in experimental in the meeting, I should have clarified that I was only talking about Option 2. Sorry for snapping at you Oliver. |
| - Primitives can't have type information | ||
| - Support for the REPL (not a whole-program transformation) | ||
|
|
||
| # Known limitations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think this approach makes resugaring for proofs harder? Or is it about as hard as it was before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also some of the same issues for visualization and extraction - we would have to de-encode to deal with them in some way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm starting to think that proofs / visualizations are no harder or easier whatever we decide
|
More detail on Option 2: supporting higher-order functions similar to C's function pointers requires the following things:
I think it makes sense to distinguish higher-order functions from closures here because only closures need to be rebuilt. |
|
@Alex-Fischman |
|
It's not that I don't want to add closures, but that I'm trying to figure out which piece is impossible to do in experimental. |
|
I see that we are discussing two interrelated problems here. So let me first separate them for clarity: (1) What variant of the unstable-fn feature will we provide in the June Vision? For (1), I claim we will not be able to come up with the "right" version due to our tight time budget. Two ways to approach the "right" answer would be (a) iterations with users as Saul suggested, which seems unlikely to happen before June; or (b) do a PL theory dive to find similar design questions that have been answered - I did some quick stabs at this but did not find an obvious answer that would serve our case well. Going down this path would also take much more effort than we have. However, we still have to decide on (1), given we will most likely get the design "wrong". This is where Zach's point comes in: whatever "wrong" thing we end up with, we should let that thing reside in the experimental while keeping the core clean. In this way, we do not prevent a future "less wrong" thing from being done. In this view, the answer to (1) is anything that we can implement while keeping the core clean. But this pushes more complexity into (2). We now need to think about not only how to accommodate the one version we pick in the core/experimental split but also potential features. "Hackability" as coined by Zach: after June, can someone pull egglog and hack a feature like this in the experimental? For comparison, egg (at the beginning) is great at this. It seems to me that moving in this direction would call for a set of "unsafe" APIs being exposed by the core to the experimental for expressive power. I imagine maybe that can only be unlocked by a combination of custom primitives + custom plugins. |
|
I was also thinking this technique could work without having to use the For the example in the PR: It could produce this program: |
No description provided.