I have a type which contains two slots, and it is important that the
types of them satisfy certain constraints. I can enforce that in the
constructor: see first and second implementations below. However, if I
want to compute types directly in the definition (see third
implementation), I end up with a TypeVar object I don't know how to deal
with (even though I read the "More about types" section in the manual,
sorry). Is this even possible?
[Note: I also asked on Gitter, but did not get a solution, or an
explanation.]
# first implementation: dd1 maps values to types
# uses constructor to constrain, works
dd1(::Int) = Float64 # for the sake of example
immutable Foo1{T,S}
a::T
b::Set{S}
function Foo1{T,S}(a::T, b::Set{S})
@assert S ≡ dd1(a)
new(a, b)
end
end
Foo1{T,S}(a::T, b::Set{S}) = Foo1{T,S}(a,b)
Foo1(1, Set([9.0])) # OK
foo1(1, Set(9)) # error
# second implementation: dd2 maps types to types
# uses constructor to constrain, works
dd2(::Type{Int}) = Float64
immutable Foo2{T,S}
a::T
b::Set{S}
function Foo2{T,S}(a::T, b::Set{S})
@assert S ≡ dd2(T)
new(a, b)
end
end
Foo2{T,S}(a::T, b::Set{S}) = Foo2{T,S}(a,b)
Foo2(1, Set([9.0])) # OK
Foo2(1, Set(9)) # error
# third implementation, types to types
immutable Foo3{T,S}
a::T
b::Set{dd2(T)}
end
## ERROR: MethodError: no method matching dd2(::TypeVar)