Thanks @johnmyleswhite . It’s clear from the comments above that this is more hassle than it’s worth for my case. All I want is to enforce the bounds on assignment. I understand @carstenbauer 's point, but that’s not a constraint for what I have in mind.
Thanks for the reference to refinement type: it’s helpful to know the right terminology when searching.
@carstenbauer You’re right: it’s the wrong reference. You’re making a good point, just not one that is relevant for what I have in mind. I should have been clearer.
Assignment in julia is not like C++ where you can overload it.
Let’s say you run ptot = p1 + p2. If you want an error when ptot is greater than 1 you need to do the check by coding it in the + method that actually get used there.
Also mathematically, a sum of probabilities is not always a probability and can be greater than 1 like @carstenbauer noted.
But it doesn’t seem like it’s true that you want only this: it sounds like you want “all existing methods for Float64, except for the constructor”, which is kind of the mirror image of creating a new primitive type.
Perhaps it’s easier to make a function that looks like a constructor and makes “Probability” objects that are really Float64 objects?
julia> function Probability(x::Float64)
if x < 0.0 || x > 1.0
error("Invalid probability")
end
x
end
Probability (generic function with 1 method)
julia> Probability(0.5)
0.5
julia> Probability(1.5)
ERROR: Invalid probability
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] Probability(x::Float64)
@ Main ./REPL[1]:3
[3] top-level scope
@ REPL[3]:1