Here’s my use case: I have a series of parametric types, Foo{T}, and I would like them to accept different values of T depending on whether or not some packages are installed.
My current code is as follows:
_allowed_species_types = [String, Symbol, MangalNode, MangalReferenceTaxon]
try
using GBIF
push!(_allowed_species_types, GBIF.GBIFTaxon)
@info "Package GBIF found: GBIFTaxon added as a species type"
catch
nothing
end
"""
...
"""
AllowedSpeciesTypes = Union{_allowed_species_types...}
The problem with making the type definition conditional is that it’s going to make your code hard to reason about and potentially dependent on the order in which you load or install packages.
Instead, how about this:
Drop the restriction on T entirely, and just let it be anything as far as the type definition is concerned. Your struct should look like:
struct Foo{T}
x::T
function Foo{T}(x::T) where {T}
... inner constructor goes here...
end
end
Then, in the inner constructor, add a check like this:
Either use subtyping (all have a common abstract supertype) , duck typing (no type restriction), or verify something at runtime. I would very much discourage trying to do almost anything based on what packages happen to be installed and especially try to constrain types based on it.