How to parameterize StepRangeLen

I have a structure with a floating point type parameter for the arrays and I want to include a StepRangeLen with fitting type. How can this be achieved?

struct MyType{S<:Union{Float32, Float64}}
  data::Vector{S}
  grid::StepRangeLen of returntype S
end

For S == Float32 the corresponding type would be StepRangeLen{Float32, Float64, Float64, Int64}
but for S == Float64 it is StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}

Has anyone a idea how to correctly parameterize the Range given the basetype S?

I guess you could just take over the StepRangeLen parameters, whatever they might be:

julia> struct MyType{T<:Union{Float32, Float64}, R, S, L}
           data::Vector{T}  # consider also adding this as a parameter of MyType (V <: AbstractVector{T})
           grid::StepRangeLen{T, R, S, L}  # or leave out L and fix Int64
       end

julia> MyType(rand(5), 1.:2.:10.)
MyType{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}([0.14483449673235382, 0.2114511579347792, 0.30870956118839, 0.2937020149713805, 0.8485098643213383], 1.0:2.0:9.0)

julia> MyType(rand(Float32, 5), 1.f0:2.f0:10.f0)
MyType{Float32, Float64, Float64, Int64}(Float32[0.34070802, 0.8333307, 0.5957912, 0.6720459, 0.24519706], 1.0f0:2.0f0:9.0f0)

It’s generally waaaay easier to ensure invariants through constructor methods than type parameter constraints. Yes, it’s not “statically enforced” but neither is Julia itself.

struct MyType{D, G}
  data::D
  grid::G
end
function MyType(data, grid)
    eltype(data) === eltype(grid) || throw(ArgumentError("blah"))
    # more checks as necessary
    return MyType{typeof(data), typeof(grid)}(data, grid)
end
4 Likes