问题
Hooking into rand
has been easier in the old days... I think I followed the description in the docs, but it doesn't seem to like a sampler returning an array:
using Random
struct Shell{N}
r0::Float64
r1::Float64
end
Base.eltype(::Type{Shell{N}}) where {N} = Array{Float64, N}
function Random.rand(rng::Random.AbstractRNG, d::Random.SamplerTrivial{Shell{N}}) where {N}
# ignore the correctness of the sampling algorithm for now :)
shell = d[]
Δ = shell.r1 - shell.r0
θ = Δ .* randn(N)
r = shell.r0 .+ θ .* .√rand(N)
end
Test:
julia> rand(Shell{2}(0, 1))
2-element Array{Float64,1}:
0.5165139561555491
0.035180151872393726
julia> rand(Shell{2}(0, 1), 2)
ERROR: MethodError: no method matching Array{Float64,2}(::Array{Float64,1})
Closest candidates are:
Array{Float64,2}(::AbstractArray{S,N}) where {T, N, S} at array.jl:498
Array{Float64,2}(::UndefInitializer, ::Int64, ::Int64) where T at boot.jl:406
Array{Float64,2}(::UndefInitializer, ::Int64...) where {T, N} at boot.jl:410
...
Stacktrace:
[1] convert(::Type{Array{Float64,2}}, ::Array{Float64,1}) at ./array.jl:490
[2] setindex!(::Array{Array{Float64,2},1}, ::Array{Float64,1}, ::Int64) at ./array.jl:782
[3] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:271 [inlined]
[4] rand! at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:266 [inlined]
[5] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:279 [inlined]
[6] rand at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:280 [inlined]
[7] rand(::Shell{2}, ::Int64) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.3/Random/src/Random.jl:283
[8] top-level scope at REPL[14]:1
What am I missing?
回答1:
Your definition of rand
always returns an Array{Float64,1}
, yet you declared that it returns Array{Float,N}
(via your definition of eltype
). This is what the error tells you: to put a freshly produced Vector{Float64}
into the result array with eltype
Array{Float64,2}
, a conversion has to be made, but no such conversion is defined, hence the error.
In this case, it seems that changing the eltype
definition to Base.eltype(::Type{<:Shell}} = Array{Float64, 1}
would solve your problem.
来源:https://stackoverflow.com/questions/62580541/implementing-a-sampler-with-array-eltype