linkz
September 29, 2023, 7:11pm
1
I am wondering if when I have two structs, say

```
mutable struct A{a, b}
str_a::a
str_b::b
end
mutable struct B{a, b, c}
str_a::a
str_b::b
str_c::c
end
```

and I alias

```
const A_num = A{<:Number}
const B_num = B{<:Number}
```

is it possible to create an abstract type, such that `A_num`

and `B_num`

would be its subtypes without `A`

and `B`

being subtypes of some abstract type?

linkz
September 29, 2023, 7:29pm
3
Well that’s a shame. Would `A`

and `B`

have to be subtypes of the same abstract type for it to be possible?

mkitti
September 29, 2023, 7:33pm
5
Could you explain the bigger picture? What are you trying to acccomplish?

linkz
September 29, 2023, 7:36pm
6
Basically trying to avoid code duplication due to `A`

and `B`

being different types. I was hoping I could somehow hack an abstract type, say `C`

, of which `A`

and `B`

would be a subtype and have `f(x::C)`

, rather than `f(x::A)`

and `f(x::B)`

(but for a lot of functions).

why do you need to add a type parameter at all?

mkitti
September 29, 2023, 7:38pm
8
Create a box type as follows. Does that help?

```
julia> abstract type AbstractBox end
julia> struct Box{T} <: AbstractBox
x::T
Box{T}(args...) where T= new{T}(T(args...))
end
julia> Base.getproperty(b::Box, s::Symbol) = getproperty(getfield(b,:x), s)
julia> mutable struct A{a, b}
str_a::a
str_b::b
end
julia> mutable struct B{a, b, c}
str_a::a
str_b::b
str_c::c
end
julia> const A_boxed = Box{A}
A_boxed (alias for Box{A})
julia> const B_boxed = Box{B}
B_boxed (alias for Box{B})
julia> x = A_boxed(1,2)
A_boxed(A{Int64, Int64}(1, 2))
julia> y = B_boxed(3,4,5)
B_boxed(B{Int64, Int64, Int64}(3, 4, 5))
julia> x isa AbstractBox
true
julia> y isa AbstractBox
true
julia> x.str_a
1
julia> x.str_b
2
julia> y.str_a
3
julia> y.str_b
4
julia> y.str_c
5
```

Edit : For completeness and tab completion:

```
Base.propertynames(x::Box) = Base.propertynames(getfield(x, :x))
```

1 Like

linkz
September 29, 2023, 7:40pm
9
It’s a complex codebase with lots of functions that depending on the input type would have to do different things in certain parts.

linkz
October 2, 2023, 9:30am
10
This is very close to what I need, except that I can’t really do (otherwise it breaks with the rest of the code that is)

```
x = A_boxed(1, 2)
y = B_boxed(3, 4, 5)
```

but I have to keep

```
x = A_boxed(1, 2)
y = B_boxed(3, 4, 5)
```

Thank you for your attempts, but I think I’ll pursue a different approach.

You can always do

```
julia> mutable struct A{a, b}
str_a::a
str_b::b
end
julia> mutable struct B{a, b, c}
str_a::a
str_b::b
str_c::c
end
julia> const A_num = A{<:Number, <:Number}
A_num (alias for A{<:Number, <:Number})
julia> const B_num = B{<:Number, <:Number, <:Number}
B_num (alias for B{<:Number, <:Number, <:Number})
julia> const AB_num = Union{A_num, B_num}
AB_num (alias for Union{A{<:Number, <:Number}, B{<:Number, <:Number, <:Number}})
julia> A("", 2) isa AB_num
false
julia> B(1//2, 2, 3/0) isa AB_num
true
julia> B(1//2, 2, 3/0)
B_num{Rational{Int64}, Int64, Float64}(1//2, 2, Inf)
```

What you cannot do is have one package create an abstract type encompassing both `A_num`

and `B_num`

(`AB_num`

in the example) and then have another package define a new subtype `struct C_num <: AB_num`

. For that kind of stuff, you should look at Holy traits.

1 Like