# Map while preserving container type

**URL:** https://discourse.julialang.org/t/map-while-preserving-container-type/58129
**Category:** New to Julia
**Tags:** question
**Created:** [March 28, 2021, 6:33pm UTC](https://discourse.julialang.org/t/map-while-preserving-container-type/58129 "2021-03-28T18:33:58Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [March 28, 2021, 6:33pm UTC](https://discourse.julialang.org/t/map-while-preserving-container-type/58129/1 "2021-03-28T18:33:58Z")

</div>

I thought `map` was supposed to preserve the type of the container but both `map` and broadcast produce `Array`s here. Why does this happen? What is the recommended way to apply a function to each element of a container while preserving the container type?

```julia
julia> gen = (x+10 for x in 1:100000); (-).(gen)
100000-element Array{Int64,1}:
     -11
     -12
...
 -100009
 -100010

julia> gen = (x+10 for x in 1:100000); map(-, gen)
100000-element Array{Int64,1}:
     -11
     -12
...
 -100009
 -100010

```

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [March 28, 2021, 9:34pm UTC](https://discourse.julialang.org/t/map-while-preserving-container-type/58129/2 "2021-03-28T21:34:48Z")

</div>

Both `map` and `broadcast` are eager, not lazy, therefore they iterate the generator to apply `-` to every element and, consequently, they return a materialization of the result. To apply a function to every element in a generator and have a generator at the end, you need to wrap your generator in another generator:

```julia
julia> gen = (x+10 for x in 1:100000); (-x for x in gen)
Base.Generator{Base.Generator{UnitRange{Int64},var"#1#2"},typeof(-)}(-, Base.Generator{UnitRange{Int64},var"#1#2"}(var"#1#2"(), 1:100000))

```

But notice that, anyway, you will change the exact type of the generator object, because it is parametrized by the range and applied function. But, at least, it is lazy, not eager.

---

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [March 29, 2021, 4:19am UTC](https://discourse.julialang.org/t/map-while-preserving-container-type/58129/3 "2021-03-29T04:19:09Z")

</div>

Is it possible to write a general `map : (x -> y) -> c x -> c y` that preserves the container type?

---

<div class="post-metadata">

### Author: ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)
#### Post date: [March 29, 2021, 4:31am UTC](https://discourse.julialang.org/t/map-while-preserving-container-type/58129/4 "2021-03-29T04:31:46Z")

</div>

Are these Haskell signatures I see here? XD

If you are talking about a method, i.e., a single body, I am not entirely sure. You could use `similar` (but I think it also materializes), or capture the container type and call it as a constructor, but the fact is that there is no general interface all collections are forced to follow that allows for creating a new object from an old object of the same type and a function to be applied to every element. If every container you are interested on accepts an iterable of the values as single parameter for the constructor, well, then you can use a generator that applies the function to every element and pass it to the constructor of the type (that you can get with `typeof` I think). But it may be some container, like `Base.ImmutableDict`, that does not act like this.

If you are talking about a function, and you are able to add new methods as you need them, well, then the sky is the limit. You can throw an error in the body that receives `container :: Any` and create a specific body for each type of container you may use.

---

<div class="post-metadata">

### Author: ![SL6Trip](https://avatars.discourse-cdn.com/v4/letter/s/4da419/32.png) [@SL6Trip](https://discourse.julialang.org/u/SL6Trip)
#### Post date: [March 29, 2021, 4:35am UTC](https://discourse.julialang.org/t/map-while-preserving-container-type/58129/5 "2021-03-29T04:35:22Z")

</div>

There is the option of `Iterators.map` which is lazy instead of the default `map` which is eager.

```julia
julia> gen = (x+10 for x in 1:100000); t = Iterators.map(-, gen);

julia> typeof(gen)
Base.Generator{UnitRange{Int64}, var"#7#8"}

julia> typeof(t)
Base.Generator{Base.Generator{UnitRange{Int64}, var"#7#8"}, typeof(-)}

```

---

<div class="post-metadata">

### Author: ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)
#### Post date: [March 29, 2021, 4:39am UTC](https://discourse.julialang.org/t/map-while-preserving-container-type/58129/6 "2021-03-29T04:39:37Z")

</div>

I think I found it as [`Kaleido.fmap`](https://tkf.github.io/Kaleido.jl/dev/#Kaleido.FLens).
