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

Implement additional simplifications for predicate function negation #51558

Open
jakobjpeters opened this issue Oct 3, 2023 · 4 comments
Open
Labels
feature Indicates new feature / enhancement requests

Comments

@jakobjpeters
Copy link
Contributor

jakobjpeters commented Oct 3, 2023

Predicate function negation (source code) (proposed in #44748 and implemented in #44752) defines a method to simplify the case of !!f to f. Based on this, I propose implementing three similar simplifications.

Current

julia> !identity
!identity

julia> !!
!(!)

julia> !(identity  !)
!(identity  (!))

Proposed

julia> Base.:!(::typeof(identity)) = !;

julia> Base.:!(::typeof(!)) = identity;

julia> Base.:!(f::ComposedFunction{typeof(identity)}) = !f.inner;

julia> !identity
! (generic function with 7 methods)

julia> !!
identity (generic function with 1 method)

julia> !(identity  !)
identity (generic function with 1 method)

As demonstrated, these methods can simplify several cases while preserving semantics. If this seems like a good idea, I'd be happy to make a PR.

@JeffBezanson
Copy link
Member

JeffBezanson commented Oct 3, 2023

This doesn't seem algebraically complete unless we have (identity ∘ !) === (!) (or for identity plus any function) and (!) ∘ (!) === identity. In fact the existing method !(f::ComposedFunction{typeof(!)}) = f.inner is suspicious; I don't know why it isn't a method of , so we need to work that out first.

@jakobjpeters
Copy link
Contributor Author

At the least, having the current single method feels either out of place or incomplete.

@jakobjpeters
Copy link
Contributor Author

Attempting to follow your suggestion, this is an improvement over my original proposal (after removing the simplifying method).

Base.:(::typeof(identity), f) = f
Base.:(::typeof(!), ::typeof(identity)) = !
Base.:(::typeof(!), ::typeof(!)) = identity
# this method is because you can still construct a `ComposedFunction(identity, f)`
Base.:(::typeof(!), f::ComposedFunction{typeof(identity)}) = !f.inner
Base.:(::typeof(!), f::ComposedFunction{typeof(!)}) = f.inner

I would also support only removing the simplifying method.

@JeffBezanson
Copy link
Member

Ah, come to think of it the problem with !(!) === identity is that ! is more restricted in what arguments it accepts than identity, so it's not really an equivalence.

@brenhinkeller brenhinkeller added the feature Indicates new feature / enhancement requests label Oct 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Indicates new feature / enhancement requests
Projects
None yet
Development

No branches or pull requests

3 participants