I have a very common problem for which I still don’t have a clear solution in Julia:

```
abstract AbstractFoo{N,T}
dimension{N,T}(::AbstractFoo{N,T}) = N
coordtype{N,T}(::AbstractFoo{N,T}) = T
abstract AbstractContainer{F}
immutable Container{F<:AbstractFoo} <: AbstractContainer{F}
state::Vector{coordtype(F)} # ERROR: MethodError: no method matching coordtype(::TypeVar)
end
```

The natural design above in which the container is parametrized by its element type doesn’t work. This problem was initially introduced in another thread but I think it deserves a thread on its own as well as a step-by-step explanation on what is the best current solution in Julia v0.5.

Issue #18466 linked in the other thread answers the question: this is not currently possible. Several workable suggestions were given there.

Thank you @ihnorton, I am looking for the best workable suggestion, it is still not clear to me.

The current solution seems to be roughly this:

- for each transformation/constraint calculated in type space, introduce a new type parameter
- check that in the inner constructor

Something along the lines of

```
abstract AbstractFoo{N,T}
dimension{N,T}(::AbstractFoo{N,T}) = N
coordtype{N,T}(::AbstractFoo{N,T}) = T
abstract AbstractContainer{F}
immutable Container{F<:AbstractFoo,S} <: AbstractContainer{F}
state::Vector{S}
function Container(state)
@assert S == coordtype(F)
new(state)
end
end
```

if I understood your problem correctly.

I used to think that this was tedious, but I now think that it is the best way to do it, because there are some constraints you can’t express in a triangular manner anyway.

1 Like

Thank you @Tamas_Papp, what do you mean by transformation/constraint?

`coordtype`

above is a transformation (function): it maps `F`

to `S`

.

More generally, one could enforce that some `g(S,F)`

holds, even when that is not amenable to a `S=h(F)`

mapping.

1 Like

Do you have an example in which a more general relation `g(S,F)`

is needed?

Suppose that for some calculation with floats, I want `F`

to be at least as precise as `S`

(in the sense of `Float16 < Float32 < Float64 < ...`

), but I don’t want to determine how precise (it’s up to the user), other than “at least `Float32`

”. So I could do

```
function g(S,F)
if S <: AbstractFloat && F <: AbstractFloat
_rank(f) = findfirst([Float16, Float32, Float64, BigFloat], f)
max(_rank(S),2) ≤ _rank(F)
else
false
end
end
```

and enforce this with the constructor.

1 Like