# Traits via set-theoretic types: proof of concept

**URL:** <https://discourse.julialang.org/t/traits-via-set-theoretic-types-proof-of-concept/97571>\
**Category:** Internals & Design\
**Created:** [April 17, 2023, 12:55pm UTC](https://discourse.julialang.org/t/traits-via-set-theoretic-types-proof-of-concept/97571 "2023-04-17T12:55:52Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jollywatt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jollywatt/32/202198_2.png) [@Jollywatt](https://discourse.julialang.org/u/Jollywatt)\
**Post date:** [April 17, 2023, 12:55pm UTC](https://discourse.julialang.org/t/traits-via-set-theoretic-types-proof-of-concept/97571/1 "2023-04-17T12:55:52Z")

</div>

I was prompted by these discussions:

- [abstract multiple inheritance · Issue #5 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/5)
- [RFC: Language Support for Traits — Yay or Nay?](https://discourse.julialang.org/t/rfc-language-support-for-traits-yay-or-nay/93914)
- … in particular, [this comment](https://discourse.julialang.org/t/rfc-language-support-for-traits-yay-or-nay/93914/26) about intersection types

and also [this excerpt](https://youtu.be/Z2LtJUe1q8c?t=1772) of Jeff Bezanson’s 2017 JuliaCon talk, where he quotes some researchers saying about intersection and complement types:

> _“Well, look, your subtyping is already so complicated, you might as well add these things…”_

and it seemed like a fascinating task to make a proof of concept:

> **[GitHub - Jollywatt/SetTheoreticTypes.jl: Proof of concept for type system...](https://github.com/Jollywatt/SetTheoreticTypes.jl)**
>
> Proof of concept for type system with unions, intersections and complements. - GitHub - Jollywatt/SetTheoreticTypes.jl: Proof of concept for type system with unions, intersections and complements.

This is a “toy” type system which

> **seems to allow a form of abstract multiple inheritance,**
>
> ```julia
> @stt begin
> abstract type Smart end
> abstract type Organic end
> 
> struct Computer ⊆ Smart end
> struct Fruit ⊆ Organic end
> struct Brain ⊆ Smart ∩ Organic end # intersection type
> 
> think(x ∈ Smart) = "$(x.value) is thinking..."
> think(x ∈ !Smart) = "$(x.value) cannot think!" # complement type
> end
> 
> ```
> 
> ```julia
> julia> Brain ⊆ Smart && Brain ⊆ Organic
> true
> 
> julia> think(Computer("Deepthought"))
> "Deepthought is thinking..."
> 
> julia> think(Fruit(:Quince))
> "Quince cannot think!"
> 
> ```

> **and appears to work with parametric types (to the extent of basic testing).**
>
> ```julia
> @stt begin
> abstract type Machine[In,Out] end
> abstract type Alive end
> struct Box[T] end
> struct Kitten ⊆ Alive end
> struct Elf[T] ⊆ Alive ∩ Machine[T,Box[T]] end
> end
> 
> ```
> 
> ```julia
> julia> Elf ⊆ Alive
> true
> 
> julia> Elf[Kitten] ⊆ @stt Machine[T,Box[T]] where T ⊆ Alive
> true
> 
> ```

But most interestingly, it has a trait-like expressiveness which allows you to “add” supertypes to types you don’t own. For example, if someone else’s package contained

```julia
@stt begin
    abstract type HasDuckBill end
    abstract type LaysEggs end
    
    abstract type Mammal end
    abstract type Bird end

    struct Platypus ⊆ HasDuckBill ∩ LaysEggs ∩ Mammal end
    struct CanadianGoose ⊆ HasDuckBill ∩ LaysEggs ∩ Bird end

    foo(x ∈ HasDuckBill ∩ LaysEggs) = "Platypus or Goose"
end

```

and you wanted to introduce a type `Alive` such that `Mammal ⊆ Alive` and `Bird ⊆ Alive`, you could do so by declaring

```julia
@stt abstract type Dead ⊆ !(Mammal ∪ Bird) end
Alive = !Dead

```

et voilà:

```julia
julia> Platypus ⊆ Alive
true

```

* * *

Overall, fully set-theoretic types seem pretty neat. Although I don’t know whether there lurk inconsistencies (either in theory or implementation). I’d be interested to know of any you find!

Also, allowing unions, intersections, complements and parameters seems fairly complex. Though what are abstract types but ways to conveniently express sets of concrete types? I’m not sure what the complexity–expressiveness balance is.

(If you’re curious about details, I invite you to look at the package tests, which I’ve tried to make fairly approachable.)

---

<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:** [April 17, 2023, 2:03pm UTC](https://discourse.julialang.org/t/traits-via-set-theoretic-types-proof-of-concept/97571/2 "2023-04-17T14:03:18Z")

</div>

> [@Jollywatt](#):
>
> and also [this excerpt](https://youtu.be/Z2LtJUe1q8c?t=1772) of Jeff Bezanson’s 2017 JuliaCon talk,

And here I thought I already memorized all content Jeff put out over the years about the type system - clearly, I am mistaken!

* * *

The one caveat I can imagine is that this is (sadly) still just half of the picture - and the other half is the nastiness with protocols Jeff mentions right after the linked section from that talk… basically associating an abstract type with what’s actually required from subtypes. Still, what a wonderful proof of concept, wish I could ❤ it more than once 🙂

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [April 18, 2023, 9:12pm UTC](https://discourse.julialang.org/t/traits-via-set-theoretic-types-proof-of-concept/97571/3 "2023-04-18T21:12:43Z")

</div>

Looks very cool! By the way, here’s an issue where Intersection types are discussed a bit: [Dispatch on a type being anywhere in a signature · Issue #39878 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/39878)
