How to unspecify parametric arguments

I want to write a method for a parametric type, where I specify some of the parameters (to have multiple dispatch) but leave some of the others alone, cause they don’t make a difference.
To my “dismay” this MWE works…

struct A{T}
    a::T
end

struct B{T}
    b::T
end

struct C{T,S}
    a::T
    b::S
end

fun(c::C{<:A, B{Int}}) = c.b.b + 1
fun(c::C{<:A, B{String}}) = println(c.b.b)

cint = C(A(false), B(1))
fun(cint)

ctxt = C(A(false), B("a"))
fun(ctxt)

But in my case I get this error when trying what I think is the same thing. Here are my definitions of two functions (this is completely out of context, so might be hard to follow):

unction temp2pixel(k, p::POI{<:Calibration,Temporal{<:AbstractTimeLine,Instantaneous}})
    ...
end
function temp2pixel(k, p::POI{<:Calibration,Temporal{<:AbstractTimeLine,Prolonged}})
    ...
end

and here’s the error I get when I try to call these functions:

ERROR: MethodError: no method matching temp2pixel(::Symbol, ::POI{Calibration{Temporal{WholeVideo,Prolonged},Temporal{WholeVideo,Instantaneous}},Temporal{WholeVideo,Instantaneous}})
Closest candidates are:
  temp2pixel(::Any, ::POI{#s7,Temporal{#s5,Instantaneous} where #s5<:AbstractTimeLine} where #s7<:Calibration) at REPL[82]:2
  temp2pixel(::Any, ::POI{#s7,Temporal{#s5,Prolonged} where #s5<:AbstractTimeLine} where #s7<:Calibration) at REPL[83]:2
Stacktrace:
 [1] top-level scope at ./REPL[86]:6 [inlined]
 [2] top-level scope at ./none:0

Basically, I have a bunch of parametric types, I want the methods to differentiate on some of these parameters but not all… I’m hoping that instead of reproducing the whole process and creating some convoluted MWE someone here might recognize the error and know what to do :slight_smile:

I really hate and recommend against using the T{<:S} syntax for this reason… Before you know the syntax, the <:S part looks like a first class object but it’s not. After you learn the syntax it seems like it should do what you expect here but it’s not…

What you want is

p::POI{T1,Temporal{T2,Instantaneous}} where {T2 <: AbstractTimeLine, T1 <: Calibration}

What you have is

p::POI{T1,Temporal{T2,Instantaneous} where {T2 <: AbstractTimeLine}} where {T1 <: Calibration}

You can see it in the error message…

::POI{#s7,Temporal{#s5,Instantaneous} where #s5<:AbstractTimeLine} where #s7<:Calibration

The difference between the two is a little subtle and the syntax really hide the difference making it hard for anyone that doesn’t have a lot of experience to catch…

5 Likes

Thank you @yuyichao!