# How to constrain the type parameters for this function

given an example function

``````function foo(a,b)
...
end
``````

`a` would accept vector of real numbers, such as `Vector{Int64}, Vector{Float64}, ...`
`b` should be Integer while elements of `a` are Integers, and Integer or Float while elements of `a` are Floats.

Here is a type constrained version

``````function foo(a::Vector{T},b::T) where {T<:Real}
...
end
``````

The problem of this version is that the Integer is not a subtype of AbstractFloat, so that

``````foo([1,2,3], 5) is allowed, and foo([1.0,2.0,3.0], 5) is not allowed, but foo([1.0,2.0,3.0], 5.0) is ok.
``````

How can i constrain the type parameters so that the desired behavior (last two invoke) be achieved in one method definition, or is it possible to do at all?

I think you want `foo(a::Vector{T1},b::T2) where {T1 <: Real, T2 <: Real}` (or `foo(a::Vector{<:Real},b::Real)` if you don’t need the type parameters).

The T2 should be Integer when T1 is Integer.

``````foo(a::Vector{<:Real},b::Real) will make
foo([1,2,3], 5.0) allowed, but is not the desired behavior
``````

The function would be an algorithm for discrete and continues domains, so when `a` is represented in discrete integers, `b` should also be integer, on the other hand, if `a` is floating points, it doesn’t matter `b` in float or integer. The original type constrained version force `b` be the same floating point type.

For the cases you want to throw (e.g. vector of integers with floating point `b`), I would add a check that throws with a helpful error message, or define a method that this case hits to throw a helpful error message.

If the types are known at compile time (i.e. the call to `foo` is typestable), this would have 0 runtime overhead in the cases you support.

If you’d prefer a `MethodError`, and you’re also handling all the cases you do support with the same implementation, then you can make that implementation an unconstrained `_foo`, and have a `foo` for each case that you do support forward there.
I’d do what is simplest (so long as they have 0 runtime overhead, which is the case for all proposals here), which depends on what `foo`’s implementation looks like.

Like if you need different implementations on input types, it’d make sense to just define those directly, and not define the type combinations you don’t support.

1 Like

so far the implementation is the same, so i wandered if i can do this in one method definition. I’ll use runtime check for now.

Note that this “runtime check” will have 0 runtime cost, because the compiler will delete it when specializing on the input types.

The revised version follows:

``````function foo(a::Vector{T},b::T1) where {T<:Real,T1<:Real}
if T <: Integer && !(T1 <: Integer)
error("b should be Integer")
end
end
``````