# Functions in Type Declarations

**URL:** https://discourse.julialang.org/t/functions-in-type-declarations/57632
**Category:** General Usage
**Tags:** question
**Created:** [March 20, 2021, 11:43pm UTC](https://discourse.julialang.org/t/functions-in-type-declarations/57632 "2021-03-20T23:43:07Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![andenrx](https://avatars.discourse-cdn.com/v4/letter/a/7993a0/32.png) [@andenrx](https://discourse.julialang.org/u/andenrx)
#### Post date: [March 20, 2021, 11:43pm UTC](https://discourse.julialang.org/t/functions-in-type-declarations/57632/1 "2021-03-20T23:43:07Z")

</div>

Is there anyway to call functions in type declarations?

For example, something like

```julia
struct ChildParent{T}
    child::Type{T}
    parent::Type{supertype{T}}
end

```

This throws `MethodError: no method matching supertype(::TypeVar)`.

I know I could do a workaround like

```julia
struct ChildParent{T, S}
    child::Type{T}
    parent::Type{S}
    function ChildParent(a::Type{T}, b::Type{S})
        if S != supertype(T)
           error("S should be of type ", supertype(T))
        end
        new{T, S}(a, b)
    end
end

```

However, this workaround is a lot more complicated and there’s an unnecessary type parameter now.

Obviously, these examples are not particularly useful, but in general is it possible to use functions in type declarations like this? If not is there a more elegant way to accomplish something like this?

---

<div class="post-metadata">

### Author: ![johnmyleswhite](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/johnmyleswhite/32/31_2.png) [@johnmyleswhite](https://discourse.julialang.org/u/johnmyleswhite)
#### Post date: [March 20, 2021, 11:47pm UTC](https://discourse.julialang.org/t/functions-in-type-declarations/57632/2 "2021-03-20T23:47:32Z")

</div>

I don’t believe this works, but it seems like it might create a lot of problems by making type information much less static. How would a type checker run without running the whole codebase? Can you use functions that haven’t been defined yet? If so, does the type definition not run at all when it’s encountered?

---

<div class="post-metadata">

### Author: ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)
#### Post date: [March 21, 2021, 12:50am UTC](https://discourse.julialang.org/t/functions-in-type-declarations/57632/3 "2021-03-21T00:50:59Z")

</div>

How about

```julia
julia> struct ChildParent{C, P}
           child::C
           parent::P
       end

julia> ChildParent(T) = ChildParent(T, supertype(T))
ChildParent

julia> ChildParent(Int)
ChildParent{DataType, DataType}(Int64, Signed)

```

EDIT: I guess this is a bit different from what the OP is asking.  
What is the context in which you would use this?

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 21, 2021, 7:07am UTC](https://discourse.julialang.org/t/functions-in-type-declarations/57632/4 "2021-03-21T07:07:17Z")

</div>

> [@andenrx](#):
>
> Is there anyway to call functions in type declarations?

No, generally you cannot do computation with type parameters in this context.

> [@andenrx](#):
>
> this workaround is a lot more complicated and there’s an unnecessary type parameter now

You can write a macro for this if you do it frequently. Also note packages like ArgCheck.jl, which would allow you to write

```julia
@argcheck S === supertype(T) 

```

instead of the `if ... end` block above.

Personally, I have grown to like this property of Julia, as it provides a clear separation between type definitions and other things like validation. This triangular pattern of validation is quite common, but far from being general. Also, if the type calculations used generic functions, it is unclear what would happen when they are redefined.

Finally, it is common practice to put “nuisance” type parameters like `S` above last, where they can be omitted in some contexts.

---

<div class="post-metadata">

### Author: ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)
#### Post date: [March 21, 2021, 2:16pm UTC](https://discourse.julialang.org/t/functions-in-type-declarations/57632/5 "2021-03-21T14:16:17Z")

</div>

You are representing `T` twice: once in the type domain as a parameter to your struct, and a second redundant time as the `child` field. The same applies for `S` in your “workaround”.  
If you do it only in the type domain, it’s much simpler, since you _can_ call functions inside the type parameters to `new` (or any function call):

```julia
julia> struct ChildParent{T,S}
           ChildParent(T) = new{T,supertype(T)}()
       end

julia> ChildParent(Int)
ChildParent{Int64,Signed}()

```

You can then access the `T` and `S` “fields” inside functions like this:

```julia
function f(cp::ChildParent{T,S}) where {T,S}
    # T and S available here
end

```

---

<div class="post-metadata">

### Author: ![andenrx](https://avatars.discourse-cdn.com/v4/letter/a/7993a0/32.png) [@andenrx](https://discourse.julialang.org/u/andenrx)
#### Post date: [March 21, 2021, 6:17pm UTC](https://discourse.julialang.org/t/functions-in-type-declarations/57632/6 "2021-03-21T18:17:45Z")

</div>

I’m not very familiar with the implementation of the type system, so I’m not sure how this would be implemented, or if it would cause problems.

The reason why I thought this might be possible is because the following works:

```julia
f(t, s) = rand() < 0.5 ? t : s
g(t, s) = Dict{t, s}

struct Test{T, S}
    a::f(T, S)
    b::g(T, S)
end

```

Then either of these works (it’s a 50-50 chance on which one)

```julia
Test{Int, String}(75, Dict(5 => "test"))
Test{Int, String}("abc", Dict(5 => "test"))

```

So you can use functions in the type declaration, but without knowing what type `T` or `S` is representing, I can’t think of a single usecase for this.
