In the code below, I had expected the three additions at the end to produce the same type. Plus, given that the constructor of Share should throw an error when its argument is outside the range 0 to 1, I would not have expected to see a matrix of type Share with values outside that range.
What is going on?
julia> mutable struct Share{đť’Ż<:Real} <:Real
x :: đť’Ż
end
julia> function Share( x :: đť’Ż ) where đť’Ż<:Real
@assert 0 ≤ x ≤ 1 "Shares must be between 0 and 1 inclusive"
return Share{đť’Ż}( x )
end
Share
julia> Base.show( io :: IO, x :: Share{đť’Ż} ) where đť’Ż <:Real = show( io, x.x )
julia> import Base: promote_rule, convert
julia> promote_rule( ::Type{ Share{đť’Ż} }, ::Type{đť’Żâ‚‚} ) where {đť’Ż <:Real, đť’Żâ‚‚ <:Real } = promote_type( đť’Ż, đť’Żâ‚‚ )
promote_rule (generic function with 103 methods)
julia> convert( ::Type{ đť’Żâ‚‚ }, x :: Share{đť’Ż} ) where {đť’Ż <:Real, đť’Żâ‚‚ <:Real } = đť’Żâ‚‚( x.x )
convert (generic function with 137 methods)
julia> Base.:+( x :: Share, y :: Share ) = Share( x.x + y.x )
julia> s = Share.( rand(20,3) );
julia> println( typeof( s .+ 1 ) )
Matrix{Float64}
julia> s .+= 1;
julia> println( typeof( s ) );
Matrix{Share{Float64}}
julia> s = s .+ 1;
julia> println( typeof( s ) );
Matrix{Float64}