# Remove parameters from struct type

**URL:** https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187
**Category:** General Usage
**Created:** [December 21, 2020, 4:12pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187 "2020-12-21T16:12:35Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)
#### Post date: [December 21, 2020, 4:12pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/1 "2020-12-21T16:12:35Z")

</div>

Hi,

Here’s a MWE:

```julia
abstract type FooBar end

struct Foo{T} <: FooBar
    a::T
end

struct Bar{T} <: FooBar
   a::T
end

struct Baz
   x
end
struct Baz2 
   x
end

Baz2(b::Baz) = Baz2(b.x)

toBaz2(fb::FooBar) = typeof(fb)(Baz2(fb.a))

toBaz2(Foo(Baz(5)))

```

EDIT: I made an example that does not rely on cuda

What happens is that this calls `Foo{Baz}(::Baz2)`, which does not work. I would like to know how to obtain only `Foo` or `Bar` where there’s currently the `typeof` function. i.e. to call `Foo(::Baz2)`.

The idea is to define generic functions that applies to any subtype of FooBar. However they throw an error because the type of the `a` field (`T`) is part of the struct type, and thus kept in `typeof`. I also tried to do `toBaz2(fb::T) where T <: FooBar`, with the same result.

Thanks !

---

<div class="post-metadata">

### Author: ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)
#### Post date: [December 21, 2020, 4:52pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/2 "2020-12-21T16:52:03Z")

</div>

`toBaz2(fb::FooBar) = Base.typename(typeof(fb)).wrapper(Baz2(fb.a))`

does it. A bit obscure for something that does not seem that weird to define.

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [December 21, 2020, 5:50pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/3 "2020-12-21T17:50:26Z")

</div>

> [@HenriDeh](#):
>
> that does not seem that weird to define.

Speak it for yourself, I could not understand what you want to get from these functions 🤣

(my comment is just to, perhaps, suggest a more clear description on what you want to achieve and why, maybe it is not clear either to someone that can actually help).

---

<div class="post-metadata">

### Author: ![HenriDeh](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrideh/32/8316_2.png) [@HenriDeh](https://discourse.julialang.org/u/HenriDeh)
#### Post date: [December 21, 2020, 6:12pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/4 "2020-12-21T18:12:16Z")

</div>

Well in short, I have a set of structures that behave differently but have the same fields. What I want to do is to define a function that moves these fields from cpu to gpu (with CUDA). Instead of defining this function for every struct I do it only for the supertype.

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [December 21, 2020, 6:28pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/5 "2020-12-21T18:28:00Z")

</div>

I’m not sure what the best approach to your problem is, but here’s a [related section of the manual](https://docs.julialang.org/en/v1/manual/methods/#Building-a-similar-type-with-a-different-type-parameter).

If nothing else, you could always just manually implement the various concrete methods that you need for `toBaz2`, instead of trying to define just one generic method. Generic methods are great, but somewhere along the line there has to be method definitions for concrete types.

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [December 21, 2020, 6:29pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/6 "2020-12-21T18:29:58Z")

</div>

@lmiq It looks like the main thrust of the problem is to have a method that converts objects of type `Foo{Baz}` into objects of type `Foo{Baz2}` (and similarly for any subtype of `FooBar`.

---

<div class="post-metadata">

### Author: ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)
#### Post date: [December 21, 2020, 6:51pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/7 "2020-12-21T18:51:03Z")

</div>

There might be a better approach, but this is the best I’ve come up with so far:

```julia
abstract type FooBar end

struct Foo{T} <: FooBar
    a::T
end

function Foo{T}(f::Foo) where T
    Foo(T(f.a))
end

struct Bar{T} <: FooBar
   a::T
end

function Bar{T}(b::Bar) where T
    Bar(T(b.a))
end

struct Baz
   x
end

struct Baz2
   x
end

Baz2(b::Baz) = Baz2(b.x)

toBaz2(fb::Foo{Baz}) = Foo{Baz2}(fb)
toBaz2(fb::Bar{Baz}) = Bar{Baz2}(fb)

toBaz2(Foo(Baz(5)))
toBaz2(Bar(Baz(5)))

```

EDIT: Must be careful, though. I’ve introduced the possibility of a stack overflow:

```julia
julia> Bar(Bar(3))
ERROR: StackOverflowError:
Stacktrace:
 [1] Bar(::Bar{Int64}) at ./REPL[4]:2
 [2] Bar{Bar{Int64}}(::Bar{Int64}) at ./REPL[5]:2
 ... (the last 2 lines are repeated 39990 more times)
 [79983] Bar(::Bar{Int64}) at ./REPL[4]:2

```

I need more coffee.

Hopefully somebody will chime in with the right way to do this.

EDIT AGAIN: Being a little more restrictive with my `Foo` and `Bar` constructors at least appears to avoid the stack overflow problem:

```julia
Foo{Baz2}(f::Foo) = Foo(Baz2(f.a))
Bar{Baz2}(f::Bar) = Bar(Baz2(f.a))

```

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [December 21, 2020, 7:28pm UTC](https://discourse.julialang.org/t/remove-parameters-from-struct-type/52187/8 "2020-12-21T19:28:47Z")

</div>

What about passing the container type as an argument?

```julia
julia> toBaz2(x,T) = T(Baz2(x.a))
toBaz2 (generic function with 1 methods)

julia> julia> x = Foo(Baz(5))

julia> toBaz2(x,Foo)
Foo{Baz2}(Baz2(Baz(5)))

```

As a side-effect you could change the supertype, who knows that is desirable.

```julia
julia> toBaz2(x,Bar)
Bar{Baz2}(Baz2(Baz(5)))

```
