Hi Daan,
versions 2 and 3 were the alternatives that I was also looking at. Just
seems to be lacking in elegance.
Is there anything that the call() syntax can provide?
Best,
Robert
On Wednesday, April 29, 2015 at 3:54:27 PM UTC+2, Daan Huybrechs wrote:
>
> At the risk of being redundant, I would like to say a bit more, because I
> remember struggling with similar constructions at first - please forgive my
> lecturing :-)
>
> Say you do include T as a parameter for Bar, then there are still several
> ways to proceed. The following seems to make syntactical sense, but it is
> not possible:
>
> type Bar{T,F <: Foo{T}}
> a::F
> b::T
> end
>
> You can not (currently) chain parameters like this. See discussions on
> 'triangular dispatch', for example #3766
> <https://github.com/JuliaLang/julia/issues/3766> and follow-ups.
>
> The following is possible:
>
> type Bar{T,F <: Foo}
> a::F
> b::T
> end
>
> This works, but here you don't enforce that the parameter of Foo is T. You
> could accidentally write Bar(Foo(2.0), 2) and mix Ints and Floats. Perhaps
> that's fine in your application, but perhaps it is not and you'll have to
> be careful when coding.
>
> One way to enforce the relation is with an inner constructor that limits F:
>
> type Bar{T,F <: Foo}
> a::F
> b::T
> Bar(a::Foo{T}, b::T) = new(a,b)
> end
>
> At this stage, you can only call this constructor as in
> Bar{Int,Foo{Int}}(Foo(2),3).
> Ideally, you can just write Bar(Foo(2),3) and that is a good reason for
> providing an outer constructor:
>
> Bar{T}(a::Foo{T},b::T) = Bar{T,typeof(a)}(a,b)
>
> This is what I find myself writing currently in cases like this, though I
> am not too fond of the 'typeof' there and I am curious about alternatives.
>
>
> On Wednesday, April 29, 2015 at 1:33:06 PM UTC+2, [email protected] wrote:
>>
>>
>>
>> On Wednesday, April 29, 2015 at 9:00:00 PM UTC+10, Robert Gates wrote:
>>>
>>> Dear Julia users:
>>>
>>> I'm trying to define a parametric composite type with fields whose types
>>> depend on both the type parameter as well as the parameter of the type
>>> parameter. This is what I tried:
>>>
>>> type Foo{T}
>>> a::T
>>> end
>>>
>>> type Bar{F <: Foo}
>>> a::F
>>> b::F.parameters[1]
>>> end
>>> ERROR: type TypeVar has no field parameters
>>>
>>> type Bar{F <: Foo{T})
>>> a::F
>>> b::T
>>> end
>>> ERROR: UndefVarError: T not defined
>>>
>>> Is there any way to achieve what I am trying to do without explicitly
>>> parametrizing Bar by T? Explicitly parametrizing would work, however, it
>>> feels redundant since T is already contained in Foo.
>>>
>>>
>> In neither case is T defined, in the first case you are using an abstract
>> Foo for which no T has been defined. And in the second you are
>> parameterising Foo by something undefined which just happens to have the
>> same name as the parameter name used in the definition of Foo.
>>
>> So bar has to be parameterised to provide the parameter to supply to Foo,
>> and to use as the field in bar.
>>
>> But note also that Foo{T} is a composite type, not an abstract type so
>> there is no type that F can have that satisfies the subtype constraint
>> (except Julia may allow Foo{T} itself, not sure).
>>
>> Cheers
>> Lex
>>
>>
>>> Best,
>>> Robert
>>>
>>>
>>>
>>>
>>>
>>>
>>>