It’s becoming a bit complicated but I think this works:
Now you can provide the signature you want to the constructor and it look through the function’s methods to find a match (returns an error otherwise)
f(z,x::Int,y::Int) = x+z
f(x::Int,y::Float64) = x+y
f(x::Int) = x
f() = 2
julia> tf1 = TypedFunction(f, (Int,Float64),(Float64))
f: Tuple{Int64,Float64} → Float64
You can use dispatch to put constrains on input/output types:
g(f::TypedFunction{T,I,O}) where {T,I<:Tuple{Number,Float64},O<:Number} = 1
julia> g(tf1)
1
Or use the function match_signature
to check if there’s a method matching the signature:
match_signature(f,(Float64,Int,Int),(Float64),false)
The last argument determine if strict check is done (==) or subtyping (<:) which makes generic functions work too:
julia> match_signature(f,(Float64,Int,Int),(Float64),false)
1-element Array{Any,1}:
f(z, x::Int64, y::Int64)
There’s probably some issues I haven’t thought about.