Getting the base type in 0.6

Given t = SomeType{Int64}, we used to be able to get SomeType via t.name.primary. That no longer works in 0.6. How should I do that? t.name still exists, but it’s a TypeName.

Alternatively, all I really want is, given an object of type SomeType{Int64}, to create a similar object of the same “base type”, but with a different instantiation of the parameter, eg. SomeType{Float64}.

3 Likes

Also, what’s the “official name” for Nullable’s relationship to Nullable{Int64}? Primary type?

The right way to do this is usually to write a function that does the conversion you want, e.g.:

Base.float{T}(x::SomeType{T}) = SomeType{float(T}}(x)

Define a method for each SomeType you want to convert.

(For example, the similar function does this for array types.)

You are not supposed to extract that to create a new type like that (see some discussion of this here).

You said you want a similar object of the same base type, well, the word similar should give you a hint

struct SomeType{T}
    field::T
end

# two possible definitions, but it would depend exactly on what you want
similar(::T, s::SomeType) where T<:SomeType = T(s.field)
similar(s::SomeType, T::Type) = SomeType{T}(s.field)

A supertype or a typename (note however that the former is ambiguous and the latter is not a type).

My use case is that I manipulate mathematical expressions such as Multiply(Variable(:x), 5), and my variable substitution algorithm might replace Variable(:x) with a number. If Multiply is parametric, I cannot use typeof(expr)(map(y->subst(y, substitutions), fieldsof(expr))...), because typeof(expr) is Multiply{Variable, Int}. It was convenient to have a generic way of traversing the tree and changing subtrees, without defining N trivial methods for my N function/predicate types, but I guess it’s no big deal.

I don’t recommend traversing the tree, but the way to do it on 0.6 is Compat.TypeUtils.typename, and then possibly a .primary field access.

1 Like