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
>>>
>>>
>>>
>>>
>>>
>>>
>>>

Reply via email to