# New concrete number type

**URL:** <https://discourse.julialang.org/t/new-concrete-number-type/55210>\
**Category:** General Usage\
**Tags:** type\
**Created:** [February 13, 2021, 3:08pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210 "2021-02-13T15:08:05Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 3:08pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/1 "2021-02-13T15:08:05Z")

</div>

Suppose that I want to define a new concrete type P (a probability). I want variables of type P to behave like floats except that e.g. passing a value of 1.1 to a function with argument of type P or assigning a value of 1.1 to an element array of elements of type P produces an error.

I have read the documentation on types, constructors, and methods but don’t know what the simplest way is of accomplishing this. Any hints?

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [February 13, 2021, 3:23pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/2 "2021-02-13T15:23:22Z")

</div>

Do you want a new primitive type: [Types · The Julia Language](https://docs.julialang.org/en/v1/manual/types/#Primitive-Types)

Or do you want a one-element struct that wraps Float64 but has a constructor that does invariant enforcement?

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 3:23pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/3 "2021-02-13T15:23:46Z")

</div>

A primitive type (if I can do enforcement).

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [February 13, 2021, 3:26pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/4 "2021-02-13T15:26:02Z")

</div>

Make a struct that wraps a float and put the test in an **inner constructor** for the struct.

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 3:30pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/5 "2021-02-13T15:30:49Z")

</div>

@dpsanders I know I can do that but then I have to type p.x \* y if I want multiplication or define all sorts of extra functions for it to otherwise behave like a float.

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 3:33pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/6 "2021-02-13T15:33:38Z")

</div>

Perhaps I should have a look at how Bool is defined.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [February 13, 2021, 3:33pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/7 "2021-02-13T15:33:47Z")

</div>

> [@Joris\_Pinkse](#):
>
> define all sorts of extra functions for it to otherwise behave like a float

Don’t you have to do that anyways? I would assume that it’s even worse if you create your own primitive type.

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [February 13, 2021, 3:34pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/8 "2021-02-13T15:34:40Z")

</div>

There are various packages for forwarding methods to new types.

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 3:38pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/9 "2021-02-13T15:38:00Z")

</div>

No. I just had a look at the definition of a Bool in https://github.com/JuliaLang/julia/blob/master/base/bool.jl Hopefully something along those lines will work.

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 3:51pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/10 "2021-02-13T15:51:45Z")

</div>

any recommendations?

---

<div class="post-metadata">

**Author:** ![smldis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/smldis/32/1735_2.png) [@smldis](https://discourse.julialang.org/u/smldis)\
**Post date:** [February 13, 2021, 3:54pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/11 "2021-02-13T15:54:54Z")

</div>

Avoid primitive types since seems like you dont need them as the manual’s warning suggests.  
The simplest way is defining a simple type:

```julia
struct Probability #<: Real eventually you can declare it as a subtype of Real if it respects Real number's algebra
    value::Float64
end

```

Then you define all the functions for manipulation that you need, for example multiplication:  
`Base.:(*)(p1::Probability,p2::Probability) = Probability(p1.value * p2.value)`

You can check out one of those packages implementing special floating point types like DoubleFloats.jl for a list of function you might want to define.  
Then maybe promotion rules and conversions if needed.  
For errors on array element assignment you can assert it when you define `setindex!`.  
Passing a value of 1.1 (a Float64) to a function with argument of type P is already an error if the function does not accept Float64.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [February 13, 2021, 3:59pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/12 "2021-02-13T15:59:06Z")

</div>

For example, there is the `@forward` macro in Lazy.jl: [Lazy.jl/macros.jl at master · MikeInnes/Lazy.jl · GitHub](https://github.com/MikeInnes/Lazy.jl/blob/master/src/macros.jl)

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [February 13, 2021, 4:04pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/13 "2021-02-13T16:04:13Z")

</div>

I don’t understand. `Bool` isn’t even defined in the file you linked. Also it contains lots of method definitions for `Bool` (making my point?).

---

<div class="post-metadata">

**Author:** ![smldis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/smldis/32/1735_2.png) [@smldis](https://discourse.julialang.org/u/smldis)\
**Post date:** [February 13, 2021, 4:08pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/14 "2021-02-13T16:08:09Z")

</div>

Also, be careful at using the type system only to catch errors, such approach has a cost in compilation time and development time.

---

<div class="post-metadata">

**Author:** ![pixel27](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pixel27/32/8902_2.png) [@pixel27](https://discourse.julialang.org/u/pixel27)\
**Post date:** [February 13, 2021, 4:09pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/15 "2021-02-13T16:09:54Z")

</div>

It sounds like to me you want a float that throws an exception when ever it’s not a valid probability. I’m guessing you want it to be in the range of 0.0 \<= x \<= 1.0. As other’s have said that’s going to be a structure with something like:

```julia
struct Probability
    value::Float64
    Probability(v) = begin
         v < 0.0 && throw("Negative probability")
         v > 1.0 && throw("Probably greater than 1.0")
         return new(v)
    end
end

```

Then you would need to define all the functions you want to use with this new type, i.e. +,\*, -, etc. I don’t think even a primitive will save you much work because you would have to define all those functions anyway.

I’m guessing what you really want, is to define a type that is really a float and have the compiler generate code to test that it’s value is inside a specific range. I don’t believe there is a way to hook the compiler like that.

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [February 13, 2021, 4:19pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/16 "2021-02-13T16:19:47Z")

</div>

Also note that probabilities aren’t just floats restricted to `[0,1]`. What is `p + q` or `p - q` supposed to mean (if you don’t know anything about the meaning of the events P and Q)?

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 5:00pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/17 "2021-02-13T17:00:25Z")

</div>

Thanks @smldis . I know I can do that.

What I want is for the new type to behave exactly as a float except that one checks the bounds on assignment without having to think of all situations in which I might want to use it and define functions accordingly.

I’ll check out the code for DoubleFloats.

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 5:01pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/18 "2021-02-13T17:01:32Z")

</div>

Thanks @carstenbauer . I want it to behave just like a float except on assignment (in which case bounds are to be checked): the probabilities were just an example.

---

<div class="post-metadata">

**Author:** ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)\
**Post date:** [February 13, 2021, 5:03pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/19 "2021-02-13T17:03:13Z")

</div>

> [@Joris\_Pinkse](#):
>
> What I want is for the new type to behave exactly as a float except that one checks the bounds on assignment without having to think of all situations in which I might want to use it and define functions accordingly.

Julia doesn’t have a mechanism that allows you to define exactly one invariant enforcing constructor and then get to act like you had the original type and delegate everything (except the constructor) to an existing type. There are approximations, as others have noted, but nothing that makes creating a [refinement type](https://en.wikipedia.org/wiki/Refinement_type) trivial.

But @carstenbauer’s point is very important to keep in mind: a new type that enforces invariants is likely not what you want. For example, you likely want adding probabilities to produce probabilities – but that means you can’t just rely on the existing methods for addition..

---

<div class="post-metadata">

**Author:** ![Joris\_Pinkse](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joris_pinkse/32/216398_2.png) [@Joris\_Pinkse](https://discourse.julialang.org/u/Joris_Pinkse)\
**Post date:** [February 13, 2021, 5:03pm UTC](https://discourse.julialang.org/t/new-concrete-number-type/55210/20 "2021-02-13T17:03:22Z")

</div>

Thanks @pixel27 . I know I can do that. What I want is for the new type to behave exactly as a float except that one checks the bounds on assignment without having to think of all situations in which I might want to use it and define functions accordingly.

What I was hoping for is some type of automatic promotion to a float via _promote\_rule_ or some such function.

[Next page](https://discourse.julialang.org/t/new-concrete-number-type/55210.md?page=2)
