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

Parameter folding for element field unions #10

Open
Mc-Zen opened this issue Jan 21, 2025 · 7 comments
Open

Parameter folding for element field unions #10

Mc-Zen opened this issue Jan 21, 2025 · 7 comments
Labels
proposal Proposal to change something in the library types Related to the type system or custom types

Comments

@Mc-Zen
Copy link

Mc-Zen commented Jan 21, 2025

For elements, folding is currently only support for single built-in types, like stroke. I'd love to somehow have folding work with e.union(stroke, none) or e.union(stroke, none, auto), probably with a custom folder.

In the standard library, this application can for example be found in rect.stroke

@PgBiel
Copy link
Owner

PgBiel commented Jan 21, 2025

It is notably supported for e.option(stroke), which is equivalent to e.union(none, stroke) (the none must come first, since none could be a valid input). It is also supported for e.smart(stroke), which is equivalent to e.union(auto, stroke).

However, I haven't implemented it (at least yet) for arbitrary unions because it can be ambiguous. Consider that you have a type A that wraps int, type B that also does so, and type C that wraps stroke. You can't know which folder to use even if A and B have different checks, since they may cast to something that doesn't satisfy the checks, and the fold would still have to work.

With that said, we can probably add an automatic implemention when the type's list of possible outputs have no intersection, in which case we can fold if you set two things of the same type, otherwise we don't.

It is worth noting, though, that you can use e.types.wrap to implement folding manually already, even if the automatic implementation isn't there yet.

@PgBiel
Copy link
Owner

PgBiel commented Jan 21, 2025

With that said, we should definitely at least implement it for e.option(e.smart(stroke)) (e.union(none, auto, stroke) or e.union(auto, none, stroke)). That was an oversight in my part.

(But note that it wouldn't be implemented for e.union(stroke, none, auto) without the more general implementation, since that's semantically different, given that unions are ordered, so if stroke were a type accepting none or auto, it would be different!)

@Mc-Zen
Copy link
Author

Mc-Zen commented Jan 21, 2025

With that said, we should definitely at least implement it for e.option(e.smart(stroke)) (e.union(none, auto, stroke) or e.union(auto, none, stroke)). That was an oversight in my part.

That would make me very happy ^^

Call it smoption 😂 (couldn't think of a worse name)

@Mc-Zen
Copy link
Author

Mc-Zen commented Jan 21, 2025

It is worth noting, though, that you can use e.types.wrap to implement folding manually already, even if the automatic implementation isn't there yet.

This sounds good. How would you do that (in a minimal example)?

@PgBiel
Copy link
Owner

PgBiel commented Jan 21, 2025

Call it smoption 😂 (couldn't think of a worse name)

Haha, it probably won't need a dedicated name and will be automatically detected :)

This sounds good. How would you do that (in a minimal example)?

You should be able to get away with something like

e.types.wrap(
  smart(option(stroke)),
  fold: old-fold => (outer, inner) => if inner in (none, auto) or outer in (none, auto) { inner } else { (e.types.native.stroke_.fold)(outer, inner) }
)

Note that old-fold can be ignored here since it's none (the folder for smart(option(stroke)) which is being overridden).

In addition, inner is the latermost / innermost set rule (should be prioritized). Here, we only fold if both are strokes, otherwise override with inner.

@PgBiel PgBiel added proposal Proposal to change something in the library types Related to the type system or custom types labels Jan 21, 2025
@Mc-Zen
Copy link
Author

Mc-Zen commented Jan 21, 2025

Works like a charm! Thank you :)

@PgBiel
Copy link
Owner

PgBiel commented Feb 5, 2025

Fwiw, regarding my original reply, I thought about it further and I think we can use the fact that unions are ordered to our advantage. We can have it work as follows: at fold time, we verify the type of the value being folded, and use the fold function from the first type with a matching output type. At least, this could be a good default and ensures we won't arbitrarily discard fold functions of things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal Proposal to change something in the library types Related to the type system or custom types
Projects
None yet
Development

No branches or pull requests

2 participants