How can I dispatch on traits relating two types, where the second type that co-satisfies the trait is uniquely determined by the first?

Certainly! Here’s the complete code incorporating the approaches discussed:

using Traits

@traitdef IsProduct{X} begin
    isnew(X) -> Bool
    coolness(X) -> Float64
end

@traitdef IsProductWithMeasurement{X,M} begin
    @constraints begin
        istrait(IsProduct{X})
    end
    measurements(X) -> M
end

type Rope
    color::String
    age_in_years::Float64
    strength::Float64
    length::Float64
end

type Paper
    color::String
    age_in_years::Int64
    content::String
    width::Float64
    height::Float64
end

function isnew(x::Rope)
    x.age_in_years < 10.0
end

function coolness(x::Rope)
    if x.color == "Orange"
        2.0
    elseif x.color != "Taupe"
        1.0
    else
        0.0
    end
end

function isnew(x::Paper)
    x.age_in_years < 1.0
end

function coolness(x::Paper)
    x.content == "StackOverflow Answers" ? 1000.0 : 0.0
end

function measurements(x::Rope)
    x.length
end

function measurements(x::Paper)
    (x.height, x.width)
end

function get_measurement_type_of_product(::Type{Rope})
    Float64
end

function get_measurement_type_of_product(::Type{Paper})
    Tuple{Float64, Float64}
end

@traitfn function get_measurements{X}(similar_items::Array{X, 1}) where {X, M}
    @traitconstraint IsProductWithMeasurement{X, M}
    all_measurements = similar_items |> map(x -> measurements(x)::M) |> collect
    all_measurements::Array{M, 1}
end

rope1 = Rope("blue", 1.0, 1.0, 1.0)
rope2 = Rope("red", 2.0, 2.0, 2.0)
paper = Paper("white", 0, "StackOverflow Answers", 8.5, 11.0)

rope_measurements = get_measurements([rope1, rope2])
paper_measurements = get_measurements([paper])

println(rope_measurements)
println(paper_measurements)

In this code, we define the traits IsProduct and IsProductWithMeasurement using the Traits.jl package. Then, we define the Rope and Paper types along with their associated functions.

To address the issue of type inference and dispatching on associated types, we introduce the get_measurement_type_of_product function. This function determines the associated type for a given base type.

Finally, we define the get_measurements function, which uses the measurements function and the associated type M to calculate the measurements of the products in the array. The @traitconstraint macro is used to enforce that X satisfies the IsProductWithMeasurement trait.

We create instances of Rope, Paper, and call get_measurements with these instances to demonstrate the usage.

Note: This code assumes that you have already installed the Traits.jl package by running ] add Traits in the Julia REPL.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)