# Get signature of function

**URL:** <https://discourse.julialang.org/t/get-signature-of-function/105156>\
**Category:** General Usage\
**Created:** [October 19, 2023, 7:08am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156 "2023-10-19T07:08:27Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [October 19, 2023, 7:08am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/1 "2023-10-19T07:08:27Z")

</div>

Is there any code analysis tool that can infer the signature of

```julia
f(x) = [x]

```

without requiring a call site? eg something that can tell me `f(x::T)` returns `Vector{T}`?

Afaik Cthulhu and JET require a concrete arglist for answering any queries.

If I wanted to build one, is it possible?

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [October 19, 2023, 8:23am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/2 "2023-10-19T08:23:16Z")

</div>

`Core.Compiler.return_type(f, Tuple{T})`?

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [October 19, 2023, 8:30am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/3 "2023-10-19T08:30:22Z")

</div>

This isn’t quite it

```julia
julia> Tuple(first(methods(f)).sig.parameters[2:end])
(Any,)

julia> Core.Compiler.return_type(f, Tuple{first(methods(f)).sig.parameters[2:end]...})
Vector (alias for Array{_A, 1} where _A)

```

because I want to get basically `f(::T)::Vector{T} where T` but that’s not what I get.

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 19, 2023, 8:31am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/4 "2023-10-19T08:31:09Z")

</div>

> [@jar1](#):
>
> `Vector (alias for Array{_A, 1} where _A)`

what do you mean? isn’t this quite literally

```julia
Vector{T} where T

```

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [October 19, 2023, 8:34am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/5 "2023-10-19T08:34:28Z")

</div>

There is no indication that the `T` in the return type is the same as the `T` in the argument.

---

<div class="post-metadata">

**Author:** ![Raf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raf/32/3383_2.png) [@Raf](https://discourse.julialang.org/u/Raf)\
**Post date:** [October 19, 2023, 8:35am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/6 "2023-10-19T08:35:13Z")

</div>

You really want that `T` printed in there ? 😂

(Sorry didn’t see your next post - it does make sense to want that connected I guess - but not sure that generalises in multiple dispatch. If you have multiple methods, it may not be the same relationship)

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [October 19, 2023, 8:41am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/7 "2023-10-19T08:41:25Z")

</div>

I don’t mind how it prints, I just want a value representing the type signature.

For example in Haskell, that is represented as a function (for a generic type `a`) from values of type `a` to values of type `[a]` (“list of `a`s”).

```julia
ghci> f x = [x]
ghci> :info f
f :: a -> [a] -- Defined at <interactive>:4:1

```

---

<div class="post-metadata">

**Author:** ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)\
**Post date:** [October 19, 2023, 9:01am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/8 "2023-10-19T09:01:15Z")

</div>

Julia is not Haskell.

You passed in Any, you get out Any. (T where T)

You need to pass in a more specific type.

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [October 19, 2023, 9:46am UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/9 "2023-10-19T09:46:13Z")

</div>

It’s a reasonable question, but yeah, julia’s type system is not equipped to deal with this sort of thing. Type inference in julia is **heavily** focused on concrete types, because every single function call has fully unconstrained potential for ad-hoc polymorphism.

Yes, in the example you gave, you could reasonably expect that the compiler should be able to predict that for any `T` you put in, a `Vector{T}` should come out, but it quickly falls apart as soon as you look at anything more complicated.

In general, the output types of a specific function call are going to depend precisely on the input types.

Haskell can avoid this because all functions have either parametric polymorphism, or polymorphism via type-classes which are both much much more rigid and constrained than julia’s approach with totally free-form multiple dispatch, and even then the Haskell compiler will sometimes need you to provide a type signature when it can’t figure out a parametric signature for a function.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 19, 2023, 12:06pm UTC](https://discourse.julialang.org/t/get-signature-of-function/105156/10 "2023-10-19T12:06:42Z")

</div>

> [@Mason](#):
>
> it quickly falls apart as soon as you look at anything more complicated.

Julia’s dynamic typing and type inference make generic functions more flexible than those in statically typed languages where you declare the return type given the parameters first, and I think you can’t infer something like the latter in most cases. Here’s a simple example where the return type depends on a generic function call, rather than the 1-element array literal in the OP:

```julia
foo(x::T) where T = bar(x)[]

bar(::Int) = String
bar(::String) = Float64
bar(::Float64) = rand(Bool, Int8, Int16, Int32, Int64, Int128)

```

Best you can say is `foo(::T)` has a return type `Vector{bar(x)}`, which isn’t the static analysis we want because it 1) is not an expression with `T`, and 2) depends on a runtime value. The `bar(::Float64)` method introduces type-instability to `foo(::Float64)`, so the compiler infers `Vector`. If we must infer by method signature instead of call signature, that’s the best we can do.
