That seems likely to work, though obviously some operations will not be 
inferrable. You might be just as happy with

type PhylogenyNode
    kind::Symbol   # :clade, etc.
    from::PhyologenyEdge
    to::Vector{PhylogenyEdge}
    confidence::Float64
end

type PhylogenyEdge
    kind::Symbol  # :branch, etc.
    from::PhylogenyNode
    to::PhylogenyNode
end

and then manually dispatching on "kind". Here, everything is inferrable.

A favorite trick (not my invention, of course) is to have root nodes point to 
themselves, so that you don't have to define a separate type for empty.

Something to consider seriously is using an established package like 
LightGraphs and storing any metadata separately. If you really want/need 
separate types for the different nodes, one advantage of this strategy is that 
at least graph traversal will be fast (inferrable)---it's only the metadata 
lookup that will be type-unstable.

--Tim

On Thursday, August 25, 2016 3:26:39 AM CDT Ben Ward wrote:
> Hi Tim,
> 
> That's a shame, I was hoping that doing the above would let me create
> several different concrete PhylogenyNode and PhylogenyEdge types, that can
> be used together. I guess since this is an abuse I have to pair one
> concrete PhylogenyEdge type with one concrete PhylogenyNode type? I
> wondered is a valid alternative to do something like this:
> 
> abstract AbstractNode
> abstract PhylogenyNode <: AbstractNode
> abstract NetworkNode <: AbstractNode
> abstract AbstractEdge
> abstract PhylogenyEdge <: AbstractEdge
> abstract NetworkEdge <: AbstractEdge
> 
> type Branch <: PhylogenyEdge
>    from::PhylogenyNode
>    to::PhylogenyNode
>    length::Float64
> 
>     function Branch()
>        x = new()
>        length!(x, -1.0)
>        return x
>    end
> end
> 
> type Clade <: PhylogenyNode
>    from::PhylogenyEdge
>    to::Vector{PhylogenyEdge}
>    confidence::Float64
> 
>     function Clade()
>        x = new()
>        x.to = Vector{PhylogenyEdge}()
>        confidence!(x, -1.0)
>        return x
>    end
> end
> 
> And define getters and setters in such a way that type assertions make
> things certain for the compiler?
> I saw that Jeff proposed a similar solution in julia issue #269 to handle
> circular type declarations.
> 
> On Wednesday, August 24, 2016 at 4:11:06 PM UTC+1, Tim Holy wrote:
> > I don't think that's type-stable. Since each node of each tree will also
> > be a
> > different type, I also think you'll end up hating life due to compile
> > times.
> > There's some (peripherally) relevant discussion at
> > http://docs.julialang.org/
> > 
> > en/latest/manual/performance-tips/#the-dangers-of-abusing-multiple-dispatc
> > h-
> > 
> > aka-more-on-types-with-values-as-parameters
> > <http://docs.julialang.org/en/latest/manual/performance-tips/#the-dangers-> 
> > > of-abusing-multiple-dispatch-aka-more-on-types-with-values-as-parameters>
> > 
> > Best,
> > --Tim
> > 
> > On Tuesday, August 23, 2016 3:28:17 PM CDT Ben Ward wrote:
> > > I'm doing some development and wondered if this kind of pattern is
> > > problematic:
> > > 
> > > abstract AbstractNode
> > > abstract PhylogenyNode <: AbstractNode
> > > abstract NetworkNode <: AbstractNode
> > > abstract AbstractEdge
> > > abstract PhylogenyEdge <: AbstractEdge
> > > abstract NetworkEdge <: AbstractEdge
> > > 
> > > type Branch{N <: PhylogenyNode} <: PhylogenyEdge
> > > 
> > >     from::N{Branch}
> > >     to::N{Branch}
> > >     length::Float64
> > >     
> > >     function Branch{N}(::Type{N})
> > >     
> > >         x = new()
> > >         length!(x, -1.0)
> > >         return x
> > >     
> > >     end
> > > 
> > > end
> > > 
> > > type Clade{E <: PhylogenyEdge} <: PhylogenyNode
> > > 
> > >     from::E
> > >     to::Vector{E}
> > >     confidence::Float64
> > >     
> > >     function Clade{E}(::Type{E})
> > >     
> > >         x = new()
> > >         x.to = Vector{E}()
> > >         confidence!(x, -1.0)
> > >         return x
> > >     
> > >     end
> > > 
> > > end
> > > 
> > > 
> > > 
> > > As you can see both concrete types are parametric, and as a result there
> > 
> > is
> > 
> > > a certain circularity to it
> > > Clade{Branch{Clade{Branch{Clade{Branch}}}}}.... That ultimately ends in
> > > something like Clade{Branch{N<:PhylogenyNode}}. I'd like to know if this
> > 
> > is
> > 
> > > type-certain or not - the fact it terminates in N<:PhylogenyNode or
> > > E<:PhylogenyEdge makes me doubt it.


Reply via email to