Error in inner constructor of a tagged struct

When I am trying to run code like this

naturalvariables = ('T', 'P', 'V', 'S')

struct NaturalVariable{tag}
    values::Matrix
    function NaturalVariable{tag}(values) where tag
        tag βˆ‰ naturalvariables && throw(DomainError("The tag must be in $(naturalvariables)!"))
        new(values)
    end
end

const Temperature = NaturalVariable{'T'}

This is the only way that goes through the type declaration and instance creation.
However, I cannot specify the type of the tag to be a Char.

julia> struct NaturalVariable{tag}
           values::Matrix
           function NaturalVariable{tag::Char}(values) where tag
               tag βˆ‰ naturalvariables && throw(DomainError("The tag must be in $(naturalvariables)!"))
               new(values)
           end
       end
ERROR: TypeError: in typeassert, expected Char, got TypeVar

or sometimes the declaration goes through, but I cannot create an instance:

julia> struct NaturalVariable{tag}
           values::Matrix
           function NaturalVariable{tag}(values) where tag <: Char
               tag βˆ‰ naturalvariables && throw(DomainError("The tag must be in $(naturalvariables)!"))
               new(values)
           end
       end

julia> NaturalVariable{'T'}(rand(4,4))
ERROR: MethodError: no method matching NaturalVariable{'T'}(::Array{Float64,2})
Stacktrace:
 [1] top-level scope at none:0

Another case:

julia> struct NaturalVariable{tag::Char}
           values::Matrix
           function NaturalVariable{tag}(values) where tag
               tag βˆ‰ naturalvariables && throw(DomainError("The tag must be in $(naturalvariables)!"))
               new(values)
           end
       end
ERROR: syntax: invalid variable expression in "where"

julia> const Temperature = NaturalVariable{'T'}
ERROR: TypeError: in NaturalVariable, in tag, expected tag<:Char, got Char

Does the parametric type only accepts types rather than instances? What’s wrong with those declarations?

As far as I know, there is no way in the current language to specify the type of a parameter in the declaration of a parameterized type. The only way to enforce that it has a certain type is in the constructor, as you have done in your first example. For example, in Base, the definition of bitarray has the form:

mutable struct BitArray{N} <: AbstractArray{Bool, N}
...
end

with no qualification on N.

1 Like