Hi
If I declare an alias such as const MyType = YourType{2}
and I implement let say Base.show(io::IO, x::MyType,...)
, I suppose it is type piracy.
However, when composing different package it is tempting to do such piracy. Here is an exemple:
I want to perform operations on arrays of measurment from the package Measurements.jl
julia> using Measurements
julia> N = 1_000_000
1000000
julia> m = measurement.(randn(N,5), rand(N,5));
julia> m[1]
-0.032 ± 0.9
julia> weightedmean(m)
-0.413120726 ± 9.6e-8
Each element of m
contains a value and its standard deviation ( and other things to propagate correlations) and I can compute its weighted mean using weightedmean(m)
However many operations on such measurements such as weightedmean
involve the precision (the inverse of the variance) rather than its std. To have a better performance (among other advantages) I prefer to bypass the sqrt(inv( ))
by storing direction the precision using the very convenient ZippedArrays package to define the alias WeightedArray{T,N}
that is an AbstractArray{Measurement{T},N}
,
const WeightedArray{T,N} = ZippedArray{Measurement{T},N,2,I,Tuple{A,B}} where {A<:AbstractArray{T,N},B<:AbstractArray{T,N},I}
ZippedArrays.build(::Type{Measurement{T}}, (val, weight)::Tuple) where {T} = measurement(val, sqrt(inv(weight)))
get_data(x::WeightedArray) = x.args[1]
get_precision(x::WeightedArray) = x.args[2]
function Measurements.weightedmean(A::WeightedArray)
precision = get_precision(A)
data = get_data(A)
Σprecision = sum(precision)
measurement(mapreduce(x -> x[1] * x[2] / Σprecision, +, zip(data, precision)), sqrt(1 / Σprecision))
end
Coded like this it is much more performant:
julia> M = WeightedArray(m);
julia> M isa AbstractArray{<:Measurement}
true
julia> m isa AbstractArray{<:Measurement}
true
julia> @btime weightedmean(m)
28.816 ms (8 allocations: 76.30 MiB)
-0.413120726 ± 9.6e-8
julia> @btime weightedmean(M)
10.765 ms (2 allocations: 96 bytes)
-0.413120726 ± 9.6e-8
The weightedmean
of Measurements.jl
could be more efficient (and I already propose a PR for that) but the issue is more general.
Coded like this function Measurements.weightedmean(A::WeightedArray)
is type piracy as I don’t own both weightedmean
and ZippedArrays
that is aliased in WeightedArray
.
My question is: what is the best way to prevent such type piracy without re-coding either most methods of one or the other package?