Proposal for ∈ isa type syntax

On the contrary. The topic is whether the is-element-of-set operator should be the same as the is-of-type operator. I was arguing that it shouldn’t by giving an example (again, within Julia) of an alternative reasonable meaning: is-convertible-to. That seems quite on-topic.

To emphasize the point a bit more, let me paste this snippet:

julia> 1//1 ∈ Set([1,2,3])
true

Under this line of reasoning, 1//1 ∈ Integer should be true.

Just to be clear – neither of these interpretations to me is sufficiently reasonable, or even sufficiently more reasonable than the other, that I think julia should provide in(needle, haystack::Type) by default.

@tamas_papp I did feel you were a bit more dismissive of my point than I deserved.

Agreed. Perhaps an even clearer example is:

julia> 1//1 ∈ typemin(Int8):typemax(Int8)
true

That range contains all the elements “in” Int8. Even if you might want to describe 1//1 as an integer value, I certainly don’t think it’s very helpful to describe it as an Int8.

3 Likes

Again, I think the key question is not philosophical or mathematical reasonableness/elegance, but

  1. whether there is a scenario where your version of x in T would be useful,
  2. whether it can be implemented in a practical way (I doubt this, but I keep an open mind).

I simply don’t agree with your proposal, and it is not fully clear to me how it would work. Perhaps if you provided an implementation, it would clarify things (I already understand that it is different from aliasing isa, which is the original proposal in this topic).

But it’s not a proposal — it’s simply pointing out the disconnect between our current semantics and isa.

  • If means that the first argument is equal to something in the collection in the second
  • and if we think of a type as a set containing all values x::T
  • then the behavior that results from x ∈ T is not isa, but rather we end up with the strange and unhelpful behavior @tkluck posted.
5 Likes

To settle the issue on what my intention is, I actually was thinking more along the lines of assigning an in function for specific types used in mathematics.

Ideally, each type would have its own parameters for the definition design of in. This means that some types in Base would need explicit definitions, and external packages could do it for their own types (if mathematically applicable).

The global example was good for stirring up the conversation though. Every object doesn’t need getindex, they also don’t all need in. However, sometimes it would be beneficial to have defined.

Thanks for clarifying, I have apparently misunderstood.

1 Like

Could you clarify why you’d want this behavior? Is it just for elegant notation or is there some context where you need to be using sets and types interchangeably?

I think this sort of behavior is unlikely to make it into base, but you can make your own Unicode modified version of \in that has the behavior you want. For instance, you can define \in\prime as follows:

(∈′)(a, B::Type) = a isa B 

julia> 1 ∈′ Integer 
true
2 Likes

It’s only for the sake of notation, for me at least.

I wanted to see what people have to say about it.

My usage would be for defining functions defined on all values of a type. For example, it would be reasonable to write

f = Fun(x-> exp(-x^2), Float64)

And have an approximation to a Gaussian that is guaranteed to be valid for all Float64. In this setting, if you want to know before calling if a function is defined at a point one can call 1 in domain(f).

Though wrappers around types give a perfectly fine implementation of the above behaviour, so there would only be minor benefit to types supporting in.

1 Like

I think You would be much better by providing a singleton Floats{Float64}() for this use;

A solution to Does type represent a set/algebraic object? problem was implemented in AbstractAlgebra.jl by exactly introducing singleton parent objects, as types (as they are in julia) are not enough to encompass whole algebraic structure on a set. Or maybe they are enough at the price of performance, which nobody likes to pay :wink:

1 Like

I am not sure I understand, is there a performance cost to eg

struct Floats{T} end

Base.in(x, ::Floats{T}) where T = x isa T

?

1 Like

no, to this one there is no performance cost;

However if Your algebraic structure is e.g. parametrized by an integer N (e.g. think modulus) and the algorithm will use a different set of Ns (depending on value of arguments), then compilation time stops being constant…