Проблема в том, что ContinuousMultivariateDistribution
и ContinuousUnivariateDistribution
являются абстрактными типами. Хотя ваши знания статистики говорят о том, что они, вероятно, должны возвращать Float64
, на уровне языка нет гарантии, что кто-то не реализует, скажем, ContinuousUnivariateDistribution
, который возвращает какой-то другой объект. Поэтому компилятор не может знать, что all ContinuousUnivariateDistribution
производит какой-либо конкретный тип.
Например, я мог бы написать:
struct BadDistribution <: ContinuousUnivariateDistribution end
Base.rand(::BadDistribution, ::Integer) = nothing
Теперь вы можете сделать NoisyLinearDataGenerator
, содержащий BadDistribution
в качестве x_dist
. Каким будет тип вывода в таком случае?
Другими словами, вывод generate
просто не может прогнозироваться только по его типам ввода.
Решить для этого вам нужно либо указать специфицированные c дистрибутивы для вашего нового типа, либо сделать параметр нового типа параметри c. В Julia, когда у нас есть поле типа, которое не может быть указано для конкретного типа, мы обычно оставляем его как параметр типа. Таким образом, одним из возможных решений является следующее:
using Distributions
struct NoisyLinearDataGenerator{X,N}
x_dist::X
noise_dist::N
weights::Vector{Float64}
function NoisyLinearDataGenerator{X,N}(x::X, n::N, w::Vector{Float64}) where {
X <: ContinuousMultivariateDistribution,
N <: ContinuousUnivariateDistribution}
return new{X,N}(x,n,w)
end
end
function NoisyLinearDataGenerator(x::X, n::N, w::Vector{Float64}) where {
X <: ContinuousMultivariateDistribution,
N <: ContinuousUnivariateDistribution}
return NoisyLinearDataGenerator{X,N}(x,n,w)
end
function generate(nl::NoisyLinearDataGenerator, N)
x = rand(nl.x_dist, N)'
e = rand(nl.noise_dist, N)
return x, x*nl.weights + e
end
nl = NoisyLinearDataGenerator(MvNormal(5, 1.0), Normal(), ones(5))
Здесь тип nl
равен NoisyLinearDataGenerator{MvNormal{Float64,PDMats.ScalMat{Float64},FillArrays.Zeros{Float64,1,Tuple{Base.OneTo{Int64}}}},Normal{Float64}}
(да, я знаю, ужасно читать), но его тип содержит всю информацию, необходимую для компилятора чтобы полностью предсказать тип вывода generate
.