# Supertype operator \<:

**URL:** https://discourse.julialang.org/t/supertype-operator/95706
**Category:** General Usage
**Tags:** type
**Created:** [March 8, 2023, 12:23am UTC](https://discourse.julialang.org/t/supertype-operator/95706 "2023-03-08T00:23:01Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [March 8, 2023, 12:23am UTC](https://discourse.julialang.org/t/supertype-operator/95706/1 "2023-03-08T00:23:01Z")

</div>

Math operators can be used in three forms

```julia
#all equivalent
1<2
<(1,2)
<(2)(1)

```

The supertype operator doesn’t seem to allow the 3rd form.

```julia
 myType <: mySuperType
<:(myType,mySuperType)
<:(mySuperType)(myType) #doesn't work

```

The 3rd form would allow:

```julia
filter( ==(mySuperType) ∘ supertype ∘ typeof, myVectorOfStructs )

```

To be written as:

```julia
filter( <:(mySuperType) ∘ typeof, myVectorOfStructs )

```

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [March 8, 2023, 5:01am UTC](https://discourse.julialang.org/t/supertype-operator/95706/2 "2023-03-08T05:01:09Z")

</div>

For what it’s worth, the `filter` could be made a little simpler by using `isa`:

```julia
julia> filter(x -> x isa Integer, Any[2, 3.14])
1-element Vector{Any}:
 2

```

The partially applied versions of operators are added on a case-by-case basis, which is a bit ad-hoc. We wouldn’t need any of those partially applied methods if we had [underscore currying](https://github.com/JuliaLang/julia/pull/24990).

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [March 8, 2023, 5:20am UTC](https://discourse.julialang.org/t/supertype-operator/95706/3 "2023-03-08T05:20:47Z")

</div>

isa doesn’t allow the 3rd form either.

```julia
a isa b
isa(a,b)
isa(b)(a) #doesnt work

```

If it did this would make the filter even simpler.

```julia
filter( isa(muSuperType), myVectOfStructs )

```

---

<div class="post-metadata">

### Author: ![Lincoln\_Hannah](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lincoln_hannah/32/19198_2.png) [@Lincoln\_Hannah](https://discourse.julialang.org/u/Lincoln_Hannah)
#### Post date: [March 8, 2023, 5:29am UTC](https://discourse.julialang.org/t/supertype-operator/95706/4 "2023-03-08T05:29:10Z")

</div>

Would it be possible to allow an expression of the form “Operator RHS” to be used in a map or filter function such that the Vector elements fill in the LHS. e.g.

```julia
map( + 1, 1:5 )

filter( < 3, 1:5 )

filter( isa Int, [1,2,"a","b"] )

```

---

<div class="post-metadata">

### Author: ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)
#### Post date: [March 8, 2023, 6:33am UTC](https://discourse.julialang.org/t/supertype-operator/95706/5 "2023-03-08T06:33:36Z")

</div>

I think I had seen a discussion about something like this, but I can’t find it now. The recommendation there was that it’s better to use `Base.Fix1/2` in such cases, as it’s much more general, and can turn any operator into a currying version.

```julia
julia> filter(Base.Fix2(isa, Int), Any[1,2,"3", 4.0])
2-element Vector{Any}:
 1
 2

```

It’s not as aesthetically pleasing, though. I think many people would like `isa(::Type)` to be available, but this might be tricky as `isa` is a built-in function currently, and methods can’t be added to it.

---

<div class="post-metadata">

### Author: ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)
#### Post date: [March 8, 2023, 6:55am UTC](https://discourse.julialang.org/t/supertype-operator/95706/6 "2023-03-08T06:55:51Z")

</div>

> [@jishnub](#):
>
> I think I had seen a discussion about something like this, but I can’t find it now.

You’re probably thinking of this

> <https://github.com/JuliaLang/julia/issues/32018>
>
> It would be nice to have a single argument \`isa\` for cleaner filtering code.
> \`\`…\`jl
> filter(x -\> !isa(x, AbstractFloat), \[1, 2.0\])
> \# could become
> filter(!isa(AbstractFloat), \[1, 2.0\])
> \`\`\`
> This would provide some consistency with other functions, such as \`isequal\`, but since \`isa\` is a builtin function, defining other variants doesn't seem trivial.
> \`\`\`jl
> julia\> Core.isa(::Type{T}) where {T} = (x) -\> isa(x, T)
> ERROR: cannot add methods to a builtin function
> \`\`\`

as well as

> <https://github.com/JuliaLang/julia/pull/37240>
>
> Currently, \`isa\` is a builtin function which causes various annoyances. For ins…tance, 
> \`\`\`julia
> julia\> @which 1 isa Int
> ERROR: ArgumentError: argument is not a generic function
> Stacktrace:
> \[1\] which(::Any, ::Any) at ./reflection.jl:1149
> \[2\] top-level scope at REPL\[14\]:1
> \`\`\`
> and it also makes it so that we can't have a curried method
> \`\`\`julia
> julia\> Core.isa(T) = x -\> x isa T
> ERROR: cannot add methods to a builtin function
> Stacktrace:
> \[1\] top-level scope at REPL\[17\]:1
> \`\`\`
> 
> This PR simply makes generic function \`Base.isa(x, T) = Core.isa(x, T)\` and adds a curried method \`isa(T) = Fix2(isa, T)\` so that we can make functions like \`isastring = isa(String)\`. 
> 
> I think this is a nice, minor convenience that costs us little to add. 
> 
> Fixes https://github.com/JuliaLang/julia/issues/32018

The underlying reason why `isa(foo)` and `<:(foo)` can’t be just defined is that they are some of the few builtin functions julia has - you can’t just add methods to it, and adding a single argument version is non-trivial.

> [@Lincoln\_Hannah](#):
>
> The 3rd form would allow:
> 
> ```julia
> filter( ==(mySuperType) ∘ supertype ∘ typeof, myVectorOfStructs )
> 
> ```
> 
> To be written as:
> 
> ```julia
> filter( <:(mySuperType) ∘ typeof, myVectorOfStructs )
> 
> ```

These are not the same - consider a type hierarchy like this:

- `mySuperType`
  - `abstract1`
    - `concrete1`

  - `abstract2`
    - `concrete2`

and filtering a vector with element type `Union{concrete1, concrete2}`. The first version of your `filter` gives an empty array, while the second one gives the input array.

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [March 8, 2023, 7:10am UTC](https://discourse.julialang.org/t/supertype-operator/95706/7 "2023-03-08T07:10:13Z")

</div>

> [@Lincoln\_Hannah](#):
>
> Math operators can be used in three forms
> 
> ```julia
> #all equivalent
> 1<2
> <(1,2)
> <(2)(1)
> 
> ```

This isn’t really generally accurate. Operators (not just maths operators) can be used in _two_ ways, infix/prefix and function call. Your third form above is just function call syntax where a single argument method has been added, which is done on a case-by-case basis. It is not generally the case that you can use the third form for operators. (For example, `+(4)` just equals `4`, and `+(4)(3)` equals `12`, not `7`, since it is parsed as multiplication by juxtaposition.)
