# What’s stopping Julia from using Boolean values as Singleton types?

**URL:** <https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898>\
**Category:** Internals & Design\
**Tags:** question, type-stability\
**Created:** [April 2, 2022, 3:30am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898 "2022-04-02T03:30:24Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![cadojo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cadojo/32/25328_2.png) [@cadojo](https://discourse.julialang.org/u/cadojo)\
**Post date:** [April 2, 2022, 3:30am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/1 "2022-04-02T03:30:24Z")

</div>

To keep type stability for functions with conditional arguments, folks often write branches like…

```julia
if arg == Val{true}
    return A
else
    return B
end

```

What would be the downside of making a special case for boolean values, since there are only two of them?

The keyword `true` would be of type `True<:Boolean`. Likewise for `false`.

This would remove the need for wrapping conditional arguments in `Val{…}` for type stability.

I’m sure there’s a good reason I’m missing for why boolean values were not designed this way. I just had this thought and was curious.

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 2, 2022, 3:32am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/2 "2022-04-02T03:32:29Z")

</div>

It would make logic operations (`&&` and `||`) type unstable.

---

<div class="post-metadata">

**Author:** ![ericphanson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ericphanson/32/215186_2.png) [@ericphanson](https://discourse.julialang.org/u/ericphanson)\
**Post date:** [April 2, 2022, 11:53am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/3 "2022-04-02T11:53:04Z")

</div>

Is that true? Since the output type is easily determined from the input type, I think it wouldn’t be. I.e. if Bools are encoded in the type domain then those functions are type-domain → type domain so I don’t think that’s really where the issue is; it’s the value domain → type domain functions like `==` which would be type unstable.

---

<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:** [April 2, 2022, 12:11pm UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/4 "2022-04-02T12:11:14Z")

</div>

Are you suggesting that booleans _always_ should be singletons, or to introduce aliases for `Val{true}` and `Val{false}`?

Keep in mind that dynamic dispatch is generally much slower than a simple branch.

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [April 2, 2022, 1:23pm UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/5 "2022-04-02T13:23:18Z")

</div>

Yes, I am not sure if `&&` and `||` would be type-unstable but they would probably incur in dynamic dispatch frequently.

---

<div class="post-metadata">

**Author:** ![sbuercklin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbuercklin/32/15728_2.png) [@sbuercklin](https://discourse.julialang.org/u/sbuercklin)\
**Post date:** [April 4, 2022, 3:46am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/6 "2022-04-04T03:46:43Z")

</div>

This would make working with an array of Bools more complicated as the array would be abstractly typed.

For cases where you want to be able to dispatch on whether something is true or false so it compiles away, it’s better to bake properties into the types under consideration if you can.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [April 4, 2022, 10:17am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/7 "2022-04-04T10:17:26Z")

</div>

It’s less about `&&` and `||` and more about the fact that it would make _every single function that returns a boolean_ type-unstable.

Operations as basic as `a < b` or `a == b`, which are as low-level and performance-critical as it gets, would become type unstable.

---

<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 4, 2022, 10:35am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/8 "2022-04-04T10:35:45Z")

</div>

> [@rdeits](#):
>
> Operations as basic as `a < b` or `a == b` , which are as low-level and performance-critical as it gets, would become type unstable.

Yeah, for this to be an option we’d need both proper dependent typing as well as a proper big SAT solver in the compiler. This would probably explode compile times.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [April 4, 2022, 7:36pm UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/9 "2022-04-04T19:36:03Z")

</div>

I’d also point out that most of the benefits this would give are already achieved by aggressive constant propagation, which Julia already does. Quite a bit more aggressively than other languages too, since we already have a call site when we set out to compile something.

---

<div class="post-metadata">

**Author:** ![Krastanov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krastanov/32/6817_2.png) [@Krastanov](https://discourse.julialang.org/u/Krastanov)\
**Post date:** [April 4, 2022, 8:16pm UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/10 "2022-04-04T20:16:43Z")

</div>

There are definitely cases where using `Val{true}` for keyword arguments to a function results in better performance and TTFX, (mainly because it forces specialization?). In the case I am linking below, turning a keyword from `true` to `Val{true}` was the way to remove spurious allocations, but that might be because of some related allocation bugs in Julia: [https://github.com/Krastanov/QuantumClifford.jl/commit/e8f94e95cc7b8d7a093a16f8022823daf5b8cb61#diff-855d2c6204b74fc940c414de72963f46190780b39a98c07035600c291b97c40cL746](https://github.com/Krastanov/QuantumClifford.jl/commit/e8f94e95cc7b8d7a093a16f8022823daf5b8cb61#diff-855d2c6204b74fc940c414de72963f46190780b39a98c07035600c291b97c40cL746)

Before this single change, the code was slow due to allocations, but the allocations were not reported in `--track-allocations`, rather only seen in `@benchmark`. After that change, everything is fine and there are no ghost allocations. Probably related to [https://github.com/JuliaLang/julia/issues/35800](https://github.com/JuliaLang/julia/issues/35800)

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [April 4, 2022, 9:29pm UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/11 "2022-04-04T21:29:22Z")

</div>

> [@Krastanov](#):
>
> There are definitely cases where using `Val{true}` for keyword arguments to a function results in better performance and TTFX, (mainly because it forces specialization?).

It might result in better performance, but it would almost certainly not result in better TTFX. Those are almost always at odds with each other. Specialization is mostly the enemy of TTFX unless the code is so slow without specialization that compiling a specialized version and running it gets results faster than running an unspecialized version. Interpretation versus compilation is just the extreme case of this where specialization is on the actual code being run (see [Futamura projections](https://en.wikipedia.org/wiki/Partial_evaluation))

---

<div class="post-metadata">

**Author:** ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)\
**Post date:** [April 5, 2022, 8:04am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/12 "2022-04-05T08:04:03Z")

</div>

In [Static.jl](https://github.com/SciML/Static.jl) there are `True` and `False` types that work with a generic `ifelse` method. The benefits of using this are:

1. Many traits follow the pattern `Trait(x)` which returns `IsTrait` or `IsNotTrait`. Using `is_trait(x) -> True/False` is immediately intuitive so that users don’t have to learn a new set of traits types to use your `is_trait` method.
2. It acts like a boolean type in more cases. For example, let’s say `is_trait(x)` returns `True()` when a certain quality is known at compile time but returns `true` when it is known dynamically (similarly with `False()` and `false`). A chain of `is_trait(x) | is_trait(y) | ... ` can return a compile time known value. I’ve only had a handful of situations where this is useful, but the amount of code to support all the `Bool` methods (~100 lines) is too much for this to be something worth implementing independently every time you need it.

As one of the authors of Static.jl, do I think it would it be nice if `if True() ... else ... end` worked? Yes, because then you could use the above example to do `if is_trait(x) ... else ... end`. Would this help improve speed? Probably not, because of constant propagation (as previously stated). Clearly we would need changes internal to base for this syntax to work, and we can’t trust that users will always define their `is_trait` in a type stable way. So we’d need something like `istrue(x::Bool) = x`, `istrue(::True) = true`, `istrue(::False) = false` at branch points to ensure we know what we’re working with. I imagine that even this simple addition could have non trivial consequences on compile times without careful implementation.

I have no idea how to do something internal like that, so If I made a PR to Base porting that code I’d really be asking a developer who knows the compiler to finish the other half of my PR. I occasionally lurk on some of the compiler development, and there’s a lot going on that has a measurable effect on compile time and run time performance.

So to answer the original question, I’d conjecture that the reason we don’t have a singleton type ever act as a boolean value in Base Julia is because the implementation is non-trivial and the only benefit of it being in Base instead of a package is a very specific syntactic nicety.

---

<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 5, 2022, 8:22am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/13 "2022-04-05T08:22:48Z")

</div>

> [@Zach\_Christensen](#):
>
> As one of the authors of Static.jl, do I think it would it be nice if `if True() ... else ... end` worked? Yes, because then you could use the above example to do `if is_trait(x) ... else ... end` . Would this help improve speed? Probably not, because of constant propagation (as previously stated). Clearly we would need changes internal to base for this syntax to work, and we can’t trust that users will always define their `is_trait` in a type stable way. So we’d need something like `istrue(x::Bool) = x` , `istrue(::True) = true` , `istrue(::False) = false` at branch points to ensure we know what we’re working with. I imagine that even this simple addition could have non trivial consequences on compile times without careful implementation.

Compile times aside, having truthy/falsy (as this would need) in a language is a big pet peeve of mine. It IMO leads to confusing code, like e.g. `if []` in python is `false` because the list is empty, while `if [1]` is true. Using a variable, both look the same (`if list`), but since there’s no clue about what type that variable is, it’s impossible to find out what will happen without knowing both type & “truthiness” implementation for that type (if desired to be user extendable). Worse yet, if you assumed this would always be a list and not switch to a `None` somewhere along the way, you may have a `else` branch expecting a list that will then only throw there, instead of at the `if` already…

I personally prefer the much clearer `if isempty(list)` (and similar explicit queries for other types), which greatly increases readability & maintainability of that piece of code.

---

<div class="post-metadata">

**Author:** ![Zach\_Christensen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/zach_christensen/32/7220_2.png) [@Zach\_Christensen](https://discourse.julialang.org/u/Zach_Christensen)\
**Post date:** [April 5, 2022, 8:34am UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/14 "2022-04-05T08:34:34Z")

</div>

I should have clarified that in my example I wouldn’t suggest `istrue` be generic or manually used at the if-else call sight. I’d expect it to be a built-in that can’t have any other definitions and be processed in the background. These sort of optionally static values can be tricky and for the time being it’s usually easier for `isempty(list)` always be `Bool` so it doesn’t break code that dispatches on `Bool`. But I don’t see any reason why Julia 2.0 couldn’t have the static version.

---

<div class="post-metadata">

**Author:** ![cadojo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cadojo/32/25328_2.png) [@cadojo](https://discourse.julialang.org/u/cadojo)\
**Post date:** [April 8, 2022, 11:53pm UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/15 "2022-04-08T23:53:22Z")

</div>

Thanks everyone!

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [April 11, 2022, 4:41pm UTC](https://discourse.julialang.org/t/what-s-stopping-julia-from-using-boolean-values-as-singleton-types/78898/16 "2022-04-11T16:41:29Z")

</div>

> [@StefanKarpinski](#):
>
> I’d also point out that most of the benefits this would give are already achieved by aggressive constant propagation, which Julia already does. Quite a bit more aggressively than other languages too, since we already have a call site when we set out to compile something.

I thought so too but was surprised to see that constant prop is not that agressive when the function is non trivial : [conservative constant prop if broadcasting is involved · Issue #44330 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/44330)
