From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

=head1 NAME
Math::PartialOrder::Base -
abstract base class for partial orders, especially datatype hierarchies.
=head1 SYNOPSIS
use Math::PartialOrder::Base;
#
# Package Variables
#
$Math::PartialOrder::Base::TYPE_TOP = '__TOP__'; # marks broken joins
$Math::PartialOrder::Base::VERBOSE = 2; # how much should we carp?
$Math::PartialOrder::Base::WANT_USER_HOOKS = 1; # run the user hooks?
#
# Construction & Initialization
#
$h = Math::PartialOrder::MyClass->new(%args); # (req) new partial order
#
# Hierarchy Manipulation
#
$newroot = $h->root($typ); # (req) set root-type
$h = $h->add($typ, @parents); # (req) add $typ under @parents
$h = $h->move($typ, @parents); # (req) move $typ to under @parents
$h = $h->remove(@types); # (req) delete all given @types
$h = $h->add_parents($typ, @parents); # (opt) add @parents over $typ
$h = $h->replace($old, $new); # (opt) replace $old with $new
$h1->ensure_types(@types); # (opt) ensure that @types are defined
$h = $h->clear(); # (opt) clear hierarchy
$h2 = $h1->clone(); # (opt) exact copy
$h1 = $h1->assign($h2); # (opt) information-cloning
$h1 = $h1->merge($h2, $h3, ...); # (opt) merge hierarchies
#
# Hierarchy Information
#
$size = $h->size(); # (opt) number of types defined
$root = $h->root(); # (req) get root-type
@leaves = $h->leaves(); # (opt) list of leaf-types
@types = $h->types(); # (req) list of all types
$bool = $h1->is_equal($h2); # (opt) test structural equivalence
$bool = $h->is_circular(); # (opt) test for circularity
$bool = $h->is_deterministic(); # (opt) test for determinism
($t1,$t2) = $h->get_nondet_pair(); # (opt) get non-deterministic type-pair
$bool = $h->is_treelike(); # (opt) test for tree-structure
$typ = $h->get_multiparent_type(); # (opt) get type with multiple parents
@types = $h->parents($typ); # (req) return all parents of $typ
@types = $h->children($typ); # (req) return all children of $typ
@types = $h->ancestors($typ); # (opt) return all ancestors of $typ
@types = $h->descendants($typ); # (opt) return all descendants of $typ
$bool = $h->has_type($typ); # (opt) boolean type-check
$bool = $h->has_types(@types); # (opt) boolean type-check
$bool = $h->has_parent($typ, $parent); # (opt) boolean parent-check
$bool = $h->has_child($typ, $child); # (opt) boolean child-check
$bool = $h->has_ancestor($typ, $ancestor); # (opt) boolean ancestor-check
$bool = $h->has_descendant($typ, $descendant); # (opt) boolean descendant-check
#
# Inheritance Operations
#
$bool = $h->subsumes($t1,$t2); # (opt) inheritance '<='
$bool = $h->properly_subsumes($t1,$t2); # (opt) inheritance '<'
$bool = $h->extends($t1,$t2); # (opt) inheritance '>='
$bool = $h->properly_extends($t1,$t2); # (opt) inheritance '>'
@lubs = $h->least_upper_bounds($t1,$t2); # (opt) lub operation
@mcds = $h->min_common_descendants($typ1,$typ2); # (opt) nontrivial lubs
$join = $h->njoin($t1,$t2,...); # (opt) determ. n-ary lub
$join = $h->type_join($typ1,$typ2,...); # (opt) ... for types only
@glbs = $h->greatest_lower_bounds($t1,$t2); # (opt) glb operation
@mcas = $h->max_common_ancestors($typ1,$typ2); # (opt) nontrivial glbs
$meet = $h->nmeet($t1,$t2,...); # (opt) determ. n-ary glb
$meet = $h->type_meet($typ1,$typ2); # (opt) ... for types only
#
# User-Defined Attributes
#
$hashref = $h->_attributes($typ); # (rcm) get user type-data hash
$h->_attributes($typ,$hashref); # (rcm) set user type-data hash
$hashref = $h->_hattributes(); # (rcm) hierarchy attributes
$h->_hattributes($hashref); # (rcm) set hierarchy attributes
$hashref = $h->get_attributes($typ); # (opt) user type-data
$val = $h->get_attribute($typ, $attr); # (opt) get user type-data
$val = $h->set_attribute($typ, $attr, $val); # (opt) set user type-data
$val = $h->get_hattribute($attr); # (opt) get user hierarchy-data
$val = $h->set_hattribute($attr, $val); # (opt) set user hierarchy-data
#
# Sorting and Comparison
#
$val = $h->compare($t1,$t2); # (opt) $val is -1, 0, 1, or undef
$val = $h->_compare($typ1,$typ2); # (opt) ... for types only
@youngest = $h->min(@types); # (opt) minimal types in @types
@eldest = $h->max(@types); # (opt) maximal types in @types
@min = $h->min_extending($base,@types); # (opt) minimal extending $base
@max = $h->max_subsuming($base,@types); # (opt) maximal subsuming $base
@sorted = $h->subsort(@types); # (opt) sort by type-subsumption
@strata = $h->stratasort(@types); # (opt) stratify by type-subsumption
$strata = $h->get_strata(@types); # (opt) get stratification-hash
#
# Compiling-Hierarchy Conventions
#
$bool = $h->compiled() # (opt) for compilable hierarchies
$bool = $h->compiled($bool2) # (opt) ensure (not) compiled
$bool = $h->compile(); # (opt) force compilation
#
# Iteration Utilities
#
$h->iterate(\&next,\&callback,\%args); # (opt) abstract iterator
$h->iterate_step(\&next,\&callback,\%args); # (opt) abstract iterator
$h->iterate_tracking(\&next,\&callback,\%args); # (opt) abstract iterator
$h->iterate_strata(\&next,\&callback,\%args); # (opt) abstract iterator
$h->iterate_pc(\&callback,\%args); # (opt) parent-to-child
$h->iterate_cp(\&callback,\%args); # (opt) child-to-parent
$h->iterate_pc_step(\&callback,\%args); # (opt) parent-to-child
$h->iterate_cp_step(\&callback,\%args); # (opt) child-to-parent
#
# Miscellaneous Utilities
#
$h->dump(); # (opt) return a dump of hierarchy contents
=head1 REQUIRES
Carp, Exporter
=head1 DESCRIPTION
This package is just an abstract placeholder for partial orders, especially
"datatype hierarchies". It was formerly called "QuD::Hierarchy".
It declares some abstract functions, which themselves call methods
which should be defined by any class inheriting from Math::PartialOrder::Base.
=head1 PACKAGE VARIABLES
=over 4
=item * C<$Math::PartialOrder::Base::TYPE_TOP>
Aliases: C<$Math::PartialOrder::Base::TYPE_NONE>
The value of this package variable is used as a return value
for failing deterministic type-join operations. It is
exportable. The default value is C<'__TOP__'>.
=item * C<$Math::PartialOrder::Base::VERBOSE>
The value of this package variable is used to determine
the amount of warning information produced when an attempt
is made to perform a deterministic hierarchy operation
(such as C<nmeet()> or C<njoin()>) on a non-deterministic
hierarchy.
Recognized values are 0 (no warnings), 1 (warn with C<carp>) and
2 (warn with C<cluck> -- prints stack backtrace).
The default value is 1.
Note that warnings will only be printed to STDERR if
C<$^W> (C<$WARNING>, if you C<use English>) is in effect.
See Also: L<Carp>, L<perlvar>.
=item * C<$Math::PartialOrder::Base::WANT_USER_HOOKS>
The value of this variable determines whether the
user-defined hooks will be called during high-level hierarchy
lookup operations such as C<subsumes()>, C<properly_subsumes()>,
C<lub()>, and C<glb()>. The default value is C<1> (true).
=back
=cut
#--------------------------------------------------------------
# Methods
#--------------------------------------------------------------
=pod
=head1 METHODS
Below is a list of abstract methods which define the interface
to Math::PartialOrder::Base objects and their descendants.
All methods are defined in Math::PartialOrder::Base, and can be optionally
overridden by subclasses unless otherwise noted.
=cut
#----------------------------------------------------------------
# Construction
#----------------------------------------------------------------
=pod
=head2 Construction and Initialization
=pod
=over 4
=item * C<new(\%args)>
I<Status: Required>
Returns a new Math::PartialOrder::Base object. This method should
recognize the following keyword arguments in the
hashref \%args:
=over 4
=item * C<< root =E<gt> $root >>
Set the initial hierarchy-root to '$root'. This implies
that $root is subsequently defined as a type in the
hierarchy.
=back
=back
=cut
#----------------------------------------------------------------
# Manipulation
#----------------------------------------------------------------
=pod
=head2 Hierarchy Manipulation
=over 4
=item * C<add($typ, @parents)>
I<Status: Required>
Adds a type named $typ with parent-types @parents (which are also
added if they do not already exist). Returns the hierarchy.
=item * C<move($typ, @parents)>
I<Status: Required>
Re-assigns a parent-types of $typ to @parents. Returns the hierarchy.
=item * C<remove($typ1, $typ2, ...)>
I<Status: Required>
Removes the types $typ1,$typ2,... from the hierarchy.
Returns the hierarchy.
'orhpaned' children of $typ1, $typ2, etc. should be
'adopted' by some type remaining in the hierarchy -- in
other words, calling this method should not alter
existing ancestor-descendant relationships for
types remaining in the hierarchy.
=item * C<add_parents($typ, @parents)>
Adds @parents to the list of parents for the type $typ. Returns the hierarchy.
=item * C<replace($old, $new)>
Inserts the (possibly new) type $new in the hierarchy in the
same position as previously occupied by $old, removing $old
from the hierarchy. Returns the hierarchy.
=item * C<ensure_types(@types)>
Ensures that all types in @types are defined. Types added
by this method will be direct children of the hierarchy-root.
Returns either @types, or, if @types is an empty list,
returns ($self-E<gt>root).
=item * C<clear()>
Clears the hierarchy. Returns the newly-cleared hierarchy.
=item * C<clone>
Returns a new hierarchy object informationally identical
to the first.
=item * C<$h1-E<gt>assign($h2)>
Makes $h1 and $h2 informationally identical. Returns $h1.
=item * C<$h1-E<gt>merge($h2, $h3, ...)>
Merges the information from hierarchies $h2,$h3,... into
the hierarchy $h1. Returns $h1 on success, undef on failure.
B<WARNING>: Attribute-values from $h2 override existing values
in $h1 for any type-attribute pairs which exist in both hierarchies.
=back
=cut
#----------------------------------------------------------------
# Information
#----------------------------------------------------------------
=pod
=head2 Hierarchy Information
=over 4
=item * C<size()>
Returns the number of types in the hierarchy.
=item * C<root()>, C<root($typ)>
I<Status: Required>
With no arguments,
returns the type representing the root of the hierarchy.
With an argument,
set the the root of the hierarchy to $typ. Returns
the new hierarchy root.
=item * C<leaves()>
Returns the types in the hierarchy which have no children.
The default implementation scans the whole hierarchy.
=item * C<types()>
I<Status: Required>
Returns a list of all types in the hierarchy.
=item * C<< $h1-E<gt>is_equal($h2) >>
Returns a true value if $h1 and $h2 are informationally
equivalent, false otherwise.
=item * C<is_circular()>, C<is_cyclic()>
Returns a true value if the hierarchy contains some type
which is an ancestor of itself, false otherwise.
=item * C<is_deterministic()>
Returns a true value if the hierarchy is a deterministic
one, also known as a "consistently complete partial order".
Really, this method just checks whether the hierarchy
contains a non-deterministic lub-pair.
=item * C<get_nondet_pair()>
Iterates over each pair of types in the hierarchy
and returns the first pair ($t1,$t2)
for which a call to C<lub($t1,$t2)> returns a list
with more than one element. Returns an empty list
if no such pair of types is found.
=item * C<is_tree()>
Returns a true value if the hierarchy has a tree-like
structure, i.e. if no type has more than one parent.
Such hierarchies are automatically deterministic,
and this method is much faster than the more general
C<is_deterministic()> method.
=item * C<get_multiparent_type()>
Iterates over each type in the hierarchy and returns the
first type with more than one parent. Returns C<undef>
if no type with multiple parents was found.
=item * C<parents($typ)>
I<Status: Required>
Returns the list of parent-types for $typ.
=item * C<ancestors($typ)>
Returns the list of all ancestor-types for $typ, in
breadth-first child-to-parent order. Ancestors accessible
by multiple paths may appear only once in the
returned list.
=item * C<children($typ)>
I<Status: Required>
Returns the list of child-types for $typ.
=item * C<descendants($typ)>
Returns the list of all descendant-types for $typ, in
breadth-first parent-to-child order. Descendants accessible
via multiple paths may appear only once in the returned
list.
=item * C<has_type($typ)>
Returns a true value if the hierarchy contains the type $typ,
and a false value otherwise.
=item * C<has_types(@types)>
Returns a true value if all of the @types are defined in
the hierarchy, false otherwise.
=item * C<has_parent($typ, $parent)>
Returns true if $parent is a direct parent of $typ, undef otherwise.
=item * C<has_child($typ, $child)>
Returns true if $child is a direct child of $typ, undef otherwise.
=item * C<has_ancestor($typ, $ancestor)>
Returns true if $parent is an ancestor of $typ, undef otherwise.
=item * C<has_descendant($typ, $descendant)>
Returns true if $parent is a descendant of $typ, undef otherwise.
=back
=cut
#----------------------------------------------------------------
# Type-Operations
#----------------------------------------------------------------
=pod
=head2 Inheritance Operations
=over 4
=item * C<subsumes($t1,$t2)>, C<le($t1,$t2)>
Returns a true value if $typ1 is at least as general as $typ2,
false otherwise. May also be called as a class-method.
Type-subsumption is determined by the following
rules:
=over 4
=item 1.
Subsumption and C<undef>
C<undef> implicitly subsumes everything, and
nothing but C<undef> subsumes C<undef>.
This rule is implemented in the exportable subroutine
C<_subsumes_trivial($t1,$t2)>.
=item 2.
Subsumption and string-equality
Otherwise, if C<$t1> and C<$t2> are string-identical
(C<$t1 eq $t2>), a true value is returned.
This rule is implemented in the exportable subroutine
C<_subsumes_trivial($t1,$t2)>.
=item 3.
Subsumption and C<$TYPE_TOP>
Everything subsumes C<$TYPE_TOP>, and
C<$TYPE_TOP> subsumes nothing but C<$TYPE_TOP>.
This rule is implemented in the exportable subroutine
C<_subsumes_trivial($t1,$t2)>.
=item 4.
User-defined subsumption
If C<$t1> is a C<CODE> reference, then
it is called with the string 'subsumes' and
C<$t2> as its arguments:
$bool = &$t1('subsumes',$t2);
$t1 should return a defined boolean
value: true if $t2 is to be considered at least as
specific as $t1, false otherwise.
Otherwise, if C<$t1> is the name of a package which defines or
inherites a method C<subsumes>, or a reference blessed
into such a package, then C<subumes()> returns whatever
C<$t1-E<gt>subsumes($t2)> returns.
This rule is implemented in the exportable subroutine
C<_subsumes_user($t1,$t2)>, and is only evaluated
if C<$WANT_USER_HOOKS> is set to a true value.
=item 5.
Subsumption as a class method
Otherwise, returns false if C<subsumes()> was
called as a class method.
=item 6.
Subsumption type-check
If C<subsumes()> was called as an instance
method, returns false unless both $t1 and
$t2 are defined in the hierarchy instance.
=item 7.
Subsumption lookup
Otherwise,
returns true if and only if $t1 has $t2
as a descendant in the hierarchy.
=back
The exportable subroutines C<_subsumes_trivial()> and C<_subsumes_user()>
return a defined boolean value if a trivial (respectively, user-defined)
solution is possible, and C<undef> otherwise.
=item * C<properly_subsumes($t1,$t2)>
Aliases: C<psubsumes()>, C<lt()>
Similar to C<subsumes()>, with the following differences:
=over 4
=item 1.
Proper subsumption and C<undef>
Returns false if both C<$t1> and C<$t2> are undefined.
This rule is implemented by the exportable subroutine
C<_properly_subsumes_trivial($t1,$t2)>.
=item 2.
Proper subsumption and string-equality
Returns false if C<$t1> is string-identical to C<$t2>.
This rule is implemented by the exportable subroutine
C<_properly_subsumes_trivial($t1,$t2)>.
=item 3.
Proper subsumption and C<$TYPE_TOP>
Returns true if C<$t2 eq $TYPE_TOP>.
This rule is implemented by the exportable subroutine
C<_properly_subsumes_trivial($t1,$t2)>.
=item 4.
User-defined proper subsumption
If C<$t1> is a C<CODE> reference then it
is evaluated with the string 'properly_subsumes' and C<$t2>
as its arguments:
$bool = &$t1('properly_subsumes', $t2);
&$t1 should return a defined boolean value indicating
the outcome of the proper-subsumption test.
Otherwise, the lookup is delegated to the method
C<$t1-E<gt>properly_subsumes($t2)>, if $t1 is a package
or blessed reference for which such a method is defined.
This rule is implemented by the exportable subroutine
C<_properly_subsumes_user($t1,$t2)>, and is only evaluated
if C<$WANT_USER_HOOKS> is set to a true value.
=item 5.
Proper subsumption as a class method
Otherwise, returns false if C<properly_subsumes()> was called as
class method.
=item 6.
Proper subsumption type-check
If C<properly_subsumes> was called as
an instance method, returns false unless both $t1 and $t2
are defined in the hierarchy.
=item 7.
Proper subsumption lookup
Returns true if and only if $t1 has $t2
as a descendant in the hierarchy instance.
=back
The exportable subroutines C<_properly_subsumes_trivial()>
and C<_properly_subsumes_user()>
return a defined boolean value if a trivial (respectively, user-defined)
solution is possible, and C<undef> otherwise.
=item * C<extends($t1,$t2)>
Aliases: C<ge()>
Really just an alias for C<subsumes($t2,$t1)>.
=item * C<properly_extends($t1,$t2)>
Aliases: C<pextends()>, C<gt()>
Really just an alias for C<properly_subsumes($t2,$t1)>.
=item * C<least_upper_bounds($t1,$t2)>
Aliases: C<lub()>
Returns the least upper bound(s) of the types $t1 and $t2 as a list.
The "least upper bounds" of two types $t1 and $t2
are defined as those subsumption-minimal types subsumed by both
$t1 and $t2. May also be called as a class method.
Least upper bounds are computed by
the following rules:
=over 4
=item 1.
LUB and C<undef>
The least upper bound of C<undef> and any value $x is $x.
This rule is implemented by the exportable subroutine
C<_lub_trivial($t1,$t2)>.
=item 2.
LUB and C<$TYPE_TOP>
The least upper bound of C<$TYPE_TOP> and any value
is C<$TYPE_TOP>.
This rule is implemented by the exportable subroutine
C<_lub_trivial($t1,$t2)>.
=item 3.
LUB and string-equality
If $t1 and $t2 are string-identical, then a list
containing the single element C<($t1)> is returned.
=item 4.
User-defined LUB (functional)
If $t1 is a C<CODE> reference, then it is evaluated
with the string 'lub' and C<$t2> as its arguments:
@lubs = &$t1('lub',$t2);
C<lub()> then returns whatever C<&$t1()> returned.
Otherwise, if C<$t2> is a C<CODE> reference, then it
is evaluated with arguments C<('lub',$t1)>, and
C<lub()> returns whatever C<&$t2()> returned.
This rule is implemented by the
exportable subroutine C<_lub_user($t1,$t2)>.
It is only evaluated if C<$WANT_USER_HOOKS> is set
to a true value.
=item 5.
User-defined LUB (object-oriented)
If $t1 is a package which defines or inherits a method
named C<lub>, or a reference blessed into such a package,
then C<lub()> returns whatever C<< $t1-E<gt>lub($t2) >>
returns.
Otherwise, if $t2 is such a package or reference,
then C<lub()> returns whatever C<< $te2-E<gt>lub($t1) >>
returns.
User-defined methods, like user-defined subroutines,
are evaluated in list context.
This rule is implemented by the
exportable subroutine C<_lub_user($t1,$t2)>.
It is only evaluated if C<$WANT_USER_HOOKS> is set
to a true value.
=item 6.
LUB as a class method
Otherwise, returns an empty list if C<lub()> was called as
a class method.
=item 7.
LUB type-check
If if C<lub()> was called as an instance-method,
returns false unless both $t1 and $t2 are defined
in the hierarchy.
=item 8.
LUB hierarchy lookup
Otherwise, the hierarchy information is consulted
and those types satisfying the criteria for least
upper bounds are returned as a list (empty on failure).
This rule is implemented by the instance-method C<_lub($t1,$t2)>.
=back
The exportable subroutines C<_lub_trivial()> and C<_lub_user()>
return array-references if a trivial (respectively, user-defined)
lub is possible, and C<undef> otherwise.
The hierarchy instance-method C<_lub()> returns a list.
=item * C<minimal_common_descendants($typ1,$typ2)>
Aliases: C<mcd()>
Returns the minimal common descendants of $typ1 and $typ2
in the hierarchy as a list. Returns the empty list on
failure.
=item * C<njoin($t1,$t2,...)>
Attempts to find and return
a single least upper bound for all the C<$t1,$t2,...>
in @types by successive calls to C<lub()>.
This method proceeds deterministically, and
will produce warnings if some call to C<lub()> returns
a list with more than one element.
If some call to C<lub()> returns an empty list, this
method returns the current value of
C<$Math::PartialOrder::Base::TYPE_TOP>.
=item * C<type_join($typ1,$typ2,...)>
Like C<njoin()>, but assumes that all of the
C<$typ1,...> arguments are types defined in the
hierarchy, bypassing C<lub()> and calling
C<_lub()> directly.
=item * C<greatest_lower_bounds($t1,$t2)>
Aliases: C<glb()>
Returns the greatest lower bound(s) of the types $t1 and $t2 as a list:
the greatest lower bounds are defined as the maximal common ancestors
of $t1 and $t2. May also be called as a class-method.
Rules for determining the glbs of $t1 and $t2
are as follows:
=over 4
=item 1.
GLB and C<undef>
If either $t1 or $t2 is C<undef>, then C<(undef)>
is returned.
This rule is implemented by the exportable subroutine
C<_glb_trivial($t1,$t2)>.
=item 2.
GLB and string-equality
If $t1 and $t2 are string-identical (C<eq>), then
C<($t1)> is returned.
This rule is implemented by the exportable subroutine
C<_glb_trivial($t1,$t2)>.
=item 3.
GLB and C<$TYPE_TOP>
If either $t1 or $t2 is $TYPE_TOP, then a list
containing only the other value is returned.
This rule is implemented by the exportable subroutine
C<_glb_trivial($t1,$t2)>.
=item 4.
User-defined GLB (functional)
If $t1 is a C<CODE> reference, then it is evaluated
with C<$t2> as its argument,
and C<glb()> returns whatever C<&$t1($t2)> returned.
Otherwise, if C<$t2> is a C<CODE> reference, then it
is evaluated with C<$t1> as its argument, and
C<glb()> returns whatever C<&$t2($t1)> returned.
User-defined GLB methods and subroutines are evaluated
in list context.
This rule is implemented by the
exportable subroutine C<_glb_user($t1,$t2)>.
It is only evaluated if C<$WANT_USER_HOOKS> is set to
a true value.
=item 5.
User-defined GLB (object-oriented)
If $typ1 is a package which defines or inherits a method
named C<glb>, or a reference blessed into such a package,
then C<glb()> returns whatever C<< $typ1-E<gt>glb($typ2) >>
returns.
Otherwise, if $typ2 is a such a package or reference,
then C<glb()> returns whatever C<< $typ2-E<gt>glb($typ1) >>
returns.
This rule is implemented by the
exportable subroutine C<_glb_user($t1,$t2)>.
It is only evaluated if C<$WANT_USER_HOOKS> is set to
a true value.
=item 6.
GLB as a class method
Otherwise, returns an empty list if C<glb()> was called as
a class method.
=item 7.
GLB type-check.
If if C<glb()> was called as an instance-method,
returns false unless both $t1 and $t2 are defined
in the hierarchy.
=item 8.
GLB lookup
Otherwise, if C<glb()> was called as an
instance-method, then the hierarchy information is consulted
and those types satisfying the criteria for greatest
lower bounds are returned as a list, which is empty
on failure.
This rule is implemented by the method C<_glb($t1,$t2)>.
=back
The exportable subroutines C<_glb_trivial()> and C<_glb_user()>
return array-references if a trivial (respectively, user-defined)
glb is possible, and C<undef> otherwise.
The hierarchy instance-method C<_glb()> returns a list.
=item * C<maximal_common_ancestors($typ1,$typ2)>
Aliases: C<mca()>
Returns the maximal common ancestors of $typ1 and $typ2
in the hierarchy as a list. Returns an empty list
on failure.
=item * C<nmeet($t1,$t2,...)>
Attempts to find and return the single greatest lowser
bound of all the C<$t1,$t2,...> arguments by successive
calls to C<glb()>.
This method proceeds deterministically, and
will produce warnings if some call to C<glb()> returns
a list with more than one element.
If some call to C<glb()> returns an empty list, this
method returns C<undef>.
=item * C<type_meet($typ1,$typ2,...)>
Like C<nmeet()>, but assumes that all of the
C<$typ1,...> arguments are types defined in the
hierarchy, bypassing C<glb()> and calling
C<_glb()> directly.
=back
=cut
#----------------------------------------------------------------
# Attributes (User-Defined Attributes)
#----------------------------------------------------------------
=pod
=head2 User-Defined Attributes
=over 4
=item * C<get_attributes($typ)>
Returns a hashref representing all the type-attributes of $typ,
or C<undef> if no attributes are defined.
=item * C<get_attribute($typ, $attr)>
Returns the value of the type-attribute $attr for the type $typ.
No attributes are assigned to any type by default.
=item * C<set_attribute($typ, $attr, $val)>
Sets the type-attribute $attr for type $typ to $val. Returns $val.
=item * C<get_hattribute($attr)>
Gets the value of the hierarchy-attribute $attr.
=item * C<set_hattribute($attr, $val)>
Sets the value of the hierarchy-attribute $attr to $val.
=item * C<_attributes($typ)>, C<_attributes($typ, $hashref)>
I<(Recommended)>
With 1 argument, returns a hashref representing all the attributes of $typ,
or C<undef> if no attributes are defined for $typ. With 2 arguments,
sets the attributes for $typ to $hashref.
=item * C<< $h-E<gt>_hattributes() >>, C<< $h-E<gt>_hattributes(\%attrs) >>
I<(Recommended)>
With no arguments, returns a hashref representing the
attributes not specific to any type in the hierarchy. With
an argument, sets the attributes for the whole hierarchy to
\%attrs. The default implementation simply calls
C<< $h-E<gt>_attributes("$h",\%attrs) >>, which may
cause difficulties if your hierarchy contains itself
as a type.
Alias: C<_hattrs>
=back
=cut
#----------------------------------------------------------------
# Sorting and Comparison
#----------------------------------------------------------------
=pod
=head2 Sorting and Comparison
=over 4
=item * C<compare($t1, $t2)>
Subsumption-comparison:
=over 4
=item 1.
Returns 0 if $t1 and $t2 are both undefined, or
if $t1 is C<eq> to $t2.
=item 2.
Returns -1 if $t1 properly subsumes $t2.
=item 3.
Returns 1 if $t2 properly subsumes $t1.
=item 4.
Otherwise, returns C<undef>.
=back
=item * C<_compare($t1, $t2)>
Like C<_compare()>, but only checks hierarchy information.
=item * C<min(@types)>
Returns the minimal types in @types: a type $t1 in @types is considered
minimal if there is no type $t2 in @types such that $t2
properly subsumes $t1. See also: C<properly_subsumes()>.
=pod
=item * C<max(@types)>
Returns the maximal types in @types: a type $t1 in @types is considered
maximal if there is no type $t2 in @types such that $t1 properly subsumes
$t2. See also: C<properly_subsumes()>.
=item * C<min_extending($base,@types)>
Returns the minimal types in C<@types> which extend the type C<$base>.
See also: C<min()>, C<extends()>.
=item * C<max_subsuming($base,@types)>
Returns the maximal types in C<@types> which subsume C<base()>.
See also: C<max()>, C<subsumes()>.
=pod
=item * C<subsort(@types)>
Retuns a sorted list containing the types in @types in
subsumption-order (oldest first). Each type in @types
occurs in the returned list exactly once.
=item * C<stratasort(@types)>
Returns a reference a list of list-references of the form
@strata = [ \@stratum1, \@stratum2, ... ]
The \@stratum listrefs contain all the types in @types; each
type in @types occurs in exactly one stratum. Types within
a single stratum are subsumption-incomparable (read: "parallel").
Strata are ordered according to disjunctive subsumption:
the types in \@stratum1 are the minimal types of @types,
whereas each type in \@stratum2 is properly subsumed by some type
in \@stratum1, etc. Types in @types not defined in the
hierarchy will be in the final stratum.
=item * C<get_strata(@types)>
Used by C<stratasort()>, this method should return a reference
to a hash of (not neccessarily consecutive) strata
(natural numbers, later used to order the strata),
indexed by type-name. The hash returned may include more
keys than just those defined in @types.
=back
=cut
#----------------------------------------------------------------
# Compiled-Hierarchy Conventions
#----------------------------------------------------------------
=pod
=head2 Compiled-Hierarchy Conventions
Hierarchies requiring internal compilation should override
the methods described in this section. The default implementations
defined in Math::PartialOrder::Base do nothing at all.
=over 4
=item * C<compiled()>, C<compiled($bool)>
If called with no arguments (1st form),
returns a true value if the hierarchy has been compiled.
Called with a true argument, attempts to compile the hierarchy
if it is not already compiled, and returns whatever compile()
returns. Called with a false argument, attempts to
de-compile the heirarchy if it is currently compiled, returning
C<undef> on failure.
The default implementation always returns 0.
=pod
=item * C<compile()>
Force compilation of compilable hierarchies. Returns
a true value on success, false otherwise. The
default implementation simply returns 1.
=back
=cut
#----------------------------------------------------------------
# Iteration Utilities
#----------------------------------------------------------------
=pod
=head2 Iteration Utilities
=over 4
=item * C<< $h-E<gt>iterate(\&next,\&callback,\%args); >>
Iterate over all each type in the hierarchy, calling
calling C<&callback($h, $t, \%args)> for each type $t in
the hierarchy. The iteration begins at the types contained
in the array-ref $args{start}, and proceeds from
these types to whatever C<\&next($h,$typ)> returns
(usually a list of types), ad infinitum.
C<$args{start}> may also be a simple scalar,
and defaults to C<< $h-E<gt>root >>.
If for any call C<&callback()> returns
a value other than C<undef>, the iteration is broken off and this
value is returned immediately.
Otherwise, returns the value of $args{return} at the end of
the iteration.
=pod
=item * C<< $h-E<gt>iterate_step(\&next,\%args); >>
Like iterate(), but visits each type at most once, and
additionally maintains the following keys of \%args:
=over 4
=item * C<< step =E<gt> $i >>
The iteration-step: $i will be 0 (zero) for the elements of
C<< $args-E<gt>{start} >>, and will be 1 for types returned
by a call to C<&next()> for those types, 2 for types returned
by a call to C<&next()> for the types for which $i was
1, etc.
=item * C<< visited =E<gt> $visited >>
A hashref to the types already visited. Keys are names of types
which will not be visited by the iteration.
=back
=pod
=item * C<< $h-E<gt>iterate_tracking(\&next,\%args); >>
Like C<iterate()>, but additionally maintains the following
keys of \%args:
=over 4
=item * C<< step =E<gt> $step >>
A natural number as for C<iterate_step()>.
=item * C<< prev =E<gt> $prev >>
A hashref indexed by type-name whose values are hashrefs keyed by
the immediate predeccessors of that type.
=back
Also, C<iterate_tracking()> recognizes the following additional
keys of \%args:
=over 4
=item * C<< ignore =E<gt> $ignored >>
A hashref of types for which which should be skipped --
&$args{callback} and &$args{next} will not be called
for types which exist as keys of C<%$ignored>.
=back
=pod
=item * C<< $h-E<gt>iterate_strata(\&next,\%args); >>
Like C<iterate()>, but additionally maintains the following
keys of \%args:
=over 4
=item * C<< step =E<gt> $thestep >>
A natural number as for C<iterate_step()>.
=item * C<< prev =E<gt> $theprev >>
A hasref as for C<iterate_tracking()>.
=back
=pod
=item * C<< $h-E<gt>iterate_pc( \%args ); >>
Calls C<iterate()> using the 'children' method for
update: iteration proceeds from
parent-types to child-types.
=pod
=item * C<< $h-E<gt>iterate_pc_step( \%args ); >>
Like C<iterate_pc()>, but uses the C<iterate_step()> method
for iteration.
=pod
=item * C<$h-E<gt>iterate_cp( \%args );>
Like iterate_pc(), but iterates from children to their ancestors.
The default value for $args{start} is C<< $h-E<gt>leaves >> .
=pod
=item * C<$h-E<gt>iterate_cp_step( \%args );>
Like iterate_cp(), but uses the C<iterate_step()> method
for iteration.
=back
=cut
#----------------------------------------------------------------
# Miscellaneous
#----------------------------------------------------------------
=pod
=head2 Miscellaneous Utilities
=over 4
=item * C<dump>
Returns a string representing the internal structure of
the object. Default behavior uses Data::Dumper.
=back
=cut
#----------------------------------------------------------------
# Miscellaneous
#----------------------------------------------------------------
=pod
=head1 EXPORTS
=over 4
=item * :typevars
The following package-variables may be imported individually,
or all at once by specifying the C<:typevars> tag to the
C<use> directive:
$TYPE_TOP
=item * :trivialities
The following subroutines may be imported individually,
or all at once by specifying the C<:trivialities> tag
to the C<use> directive:
&_subsumes_trivial
&_psubsumes_trivial
&_lub_trivial
&_glb_trivial
=item * :userhooks
The following subroutines may be imported individually,
or all together by specifying the C<:userhooks> tag
to the C<use> directive:
&_subsumes_user
&_psubsumes_user
&_lub_user
&_glb_user
&_binop_user
C<_binop_user> is a low-level subroutine which is called by the
C<_lub_user()> and C<_glb_user()> methods.
=back
Nothing is exported by default.
See also:
L<PACKAGE VARIABLES>,
C<subsumes()>,
C<properly_subsumes()>,
C<lub()>,
C<glb()>.
=cut
#----------------------------------------------------------------
# Footer
#----------------------------------------------------------------
=pod
=head1 ACKNOWLEDGEMENTS
perl by Larry Wall.
=head1 AUTHOR
Bryan Jurish E<lt>jurish@ling.uni-potsdam.deE<gt>
=head1 COPYRIGHT
Copyright (c) 2001, Bryan Jurish. All rights reserved.
This package is free software. You may redistribute it
and/or modify it under the same terms as Perl itself.
=head1 SEE ALSO
perl(1).
Math::PartialOrder(3pm).
Math::PartialOrder::Loader(3pm).
Math::PartialOrder::Std(3pm).
Math::PartialOrder::Caching(3pm).
Math::PartialOrder::LRUCaching(3pm).
Math::PartialOrder::CMasked(3pm).
Math::PartialOrder::CEnum(3pm).
Data::Dumper(3pm).