# Is there a function to make an abstractly-typed variable "more" concrete?

**URL:** <https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439>\
**Category:** Performance\
**Tags:** type-stability\
**Created:** [July 10, 2023, 3:52pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439 "2023-07-10T15:52:11Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)\
**Post date:** [July 10, 2023, 3:52pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/1 "2023-07-10T15:52:11Z")

</div>

Is there a way to find the most concrete type representation of a variable and apply it ?

## For example

say we got our hands to a `Dict{Any, Any}`

```julia-auto
julia> d = Dict{Any,Any}("one" => 1, "two" => 2)
Dict{Any, Any} with 2 entries:
  "two" => 2
  "one" => 1

```

it would be great if we could do

```julia-auto
julia> conretisize(d)
Dict{String, Int64} with 2 entries:
  "two" => 2
  "one" => 1

```

and get back the most accurate typed version.

Similarly, `Number[1, 2.0, 3]` could be transformed to `Float64[]` and maybe `Vector{Any}([1,missing, 2])` could be transformed to something like `Vector{Union{Missing, Int64}}`.

## Remarks

Ofc, one could customize such an operation w.r.t. the situation. E.g., above we could get the type stable representation by doing `Dict(k => v for (k,v) in d)` for `Dict`s and `[v for v in vector]` for `Vector`s.  
But I am wondering whether a more general implementation can be provided, that would work for all types.  
If generalizing is hard, do you think it’s worth to provide it as an interface that could/should be implemented by the developers for newly defined structs ?

It’s obvious that `conretisize` cannot always return concrete type, so maybe the naming is a bit misleading.

As I understand it, this operation cannot be done in place as the memory representation changes.

I think this could be very useful to call in the middle of some functions to kill some type instabilities, if used together with the function barrier pattern.  
(_some more context [in zulip](https://julialang.zulipchat.com/#narrow/stream/137791-general/topic/auto.20function.20barrier.20type.20instabilities.20improvement) mentioned as `trytoinfer`, but this post can be treated independently._)

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [July 10, 2023, 4:56pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/2 "2023-07-10T16:56:23Z")

</div>

> [@filchristou](#):
>
> If generalizing is hard, do you think it’s worth to provide it as an interface that could/should be implemented by the developers for newly defined structs ?

Seems like a good idea. If you create a package, perhaps it should build upon ConstructionBase:

> **[GitHub - JuliaObjects/ConstructionBase.jl: Primitives for construction of...](https://github.com/JuliaObjects/ConstructionBase.jl)**
>
> Primitives for construction of objects. Contribute to JuliaObjects/ConstructionBase.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![joa-quim](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joa-quim/32/227_2.png) [@joa-quim](https://discourse.julialang.org/u/joa-quim)\
**Post date:** [July 10, 2023, 6:19pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/3 "2023-07-10T18:19:14Z")

</div>

I would love to have such a function. Parsing Dict{Symbol, Any} is a Any’s plague, even when we know for sure the type of _value_.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [July 10, 2023, 8:13pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/4 "2023-07-10T20:13:10Z")

</div>

As a start, would a generic function work for you?

```julia
# narrowtype(x) = x # define if it shall not fail
narrowtype(x::Dict) = Dict(k => v for (k, v) in d)
narrowtype(x::AbstractArray) = map(identity, x)
# ...

```

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [July 10, 2023, 8:28pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/5 "2023-07-10T20:28:05Z")

</div>

In some cases, broadcasting `identity` is all that you need:

```julia
julia> x = Any[1, 2, 3];

julia> typeof(identity.(x))
Vector{Int64} (alias for Array{Int64, 1})

julia> y = Any[1, 2, 3.0];

julia> typeof(identity.(y))
Vector{Real} (alias for Array{Real, 1})

```

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [July 10, 2023, 8:30pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/6 "2023-07-10T20:30:30Z")

</div>

“Shallow” narrowing is easy as shown here, while “recursive” is nontrivial but would also be nice.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [July 11, 2023, 5:32am UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/7 "2023-07-11T05:32:44Z")

</div>

Work on this might be coordinated with this package that just got registered:

> **[GitHub - emmt/TypeUtils.jl: Methods for dealing with types in Julia](https://github.com/emmt/TypeUtils.jl)**
>
> Methods for dealing with types in Julia. Contribute to emmt/TypeUtils.jl development by creating an account on GitHub.

Edit: @emmt

---

<div class="post-metadata">

**Author:** ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)\
**Post date:** [July 11, 2023, 7:00am UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/8 "2023-07-11T07:00:06Z")

</div>

The promise is to be memory efficient, i.e. type stable. I noticed there are cases like that of Guillaume’s

```julia
julia> typeof(identity.(Any[1, 2, 3.0]))
Vector{Real} (alias for Array{Real, 1})

```

that do narrow the type but still are type instable.  
I think in such cases some promotion needs to take place, e.g.:

```julia
julia> typeof(collect(promote(Any[1, 2, 3.0]...)))
Vector{Float64} (alias for Array{Float64, 1})

```

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [July 11, 2023, 11:06am UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/9 "2023-07-11T11:06:20Z")

</div>

> [@filchristou](#):
>
> type stable

I think you’re using that phrase wrong.

> [@filchristou](#):
>
> some promotion needs to take place

This is a completely different goal than above. Sometimes one is useful, sometimes the other.

---

<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:** [July 11, 2023, 12:41pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/10 "2023-07-11T12:41:18Z")

</div>

You mostly certainly will need to allocate a new data structure for the narrowed container, so the memory usage from type-unstability does not seem like a big concern here.

But if you want type-stability the _only_ way is for the function to take an argument for which its type guarantees the type of the output, like a `convert` that only takes concrete types.

---

<div class="post-metadata">

**Author:** ![filchristou](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/filchristou/32/26760_2.png) [@filchristou](https://discourse.julialang.org/u/filchristou)\
**Post date:** [July 11, 2023, 5:20pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/11 "2023-07-11T17:20:53Z")

</div>

@nsajko

> I think you’re using that phrase wrong.

Yes that was misleading, I was referring to memory efficiency as having the appropriate representation to make efficient computations.

> This is a completely different goal than above.

The goal is solely to try to get concrete types. For this, both type-narrowing and promotion could be useful as demonstrated.

@Henrique_Becker

> But if you want type-stability the _only_ way is for the function to take an argument for which its type guarantees the type of the output, like a `convert` that only takes concrete types.

And the guaranteed type must also be concrete right ? Just want to make sure everybody is on the same page.

---

<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:** [July 11, 2023, 7:31pm UTC](https://discourse.julialang.org/t/is-there-a-function-to-make-an-abstractly-typed-variable-more-concrete/101439/12 "2023-07-11T19:31:37Z")

</div>

> [@filchristou](#):
>
> And the guaranteed type must also be concrete right ? Just want to make sure everybody is on the same page.

Yes. But note that a type like `Vector{Real}` is concrete, it is accessing its elements that may cause type-instability.
