This page demonstrates one of the very early attempts to do something similar to MuPAD? combinat's "decomposable objects" in Aldor/Axiom.  Meanwhile, we adopted the point of view of species, as shown on SandBoxSpecies?
aldor
#include "axiom.as"
macro CCC == CombinatorialClassCategory;
import from Integer;
import from List Integer;
import from OutputForm;
CombinatorialClassCategory: Category == with {        
        list: Integer -> List %;
        count: Integer -> Integer;
        import from NonNegativeInteger;
        default count(i: Integer): Integer == (#list(i))::Integer;
        coerce: % -> OutputForm;
} 
Primitive(n: Integer): CombinatorialClassCategory == add {
        Rep == Integer;
        count(i: Integer): Integer == if i=n then 1 else 0;
        list(i: Integer): List % == if i=n then [per 1] else [];
        coerce(x: %): OutputForm == message(" ")
}
Epsilon: CombinatorialClassCategory == Primitive(0) add;
Atom: CombinatorialClassCategory == Primitive(1) add;
UnionClass(S1: CCC, S2: CCC): CCC == add {
        Rep == Union(s1: S1, s2: S2);
        count(i: Integer): Integer == count(i)$S1 + count(i)$S2;
        import from Rep;
        import from List S1;
        import from List S2;
        list(i: Integer): List % == {
                result: List % := [];
                for a in list(i)$S1 repeat result := cons(per union a, result);
                for b in list(i)$S2 repeat result := cons(per union b, result);
                result;
        }
        coerce(x: %): OutputForm == {
                (rep x) case s1 => ((rep x).s1)::OutputForm;
                ((rep x).s2)::OutputForm;
        }
}
CrossClass(S1: CCC, S2: CCC): with {
        CombinatorialClassCategory
} == add {
        Rep == Record(t1: S1, t2: S2);
        count(i: Integer): Integer == {
                result := 0;
                for k in 1 .. i-1 repeat {
                        result := result + count(k)$S1 * count(i-k)$S2;
                }
                result;
        }
        import from Rep;
        import from List S1;
        import from List S2;
        list(i: Integer): List % == {
                result: List % := [];
                for k in 1..i-1 repeat {
                  for a in list(k)$S1 repeat {
                    for b in list(i-k)$S2 repeat {
                      result := cons(per record(a, b), result);
                    }
                  }
                }
                result;
        }
        coerce(x: %): OutputForm == {
                a := ((rep x).t1)::OutputForm;
                b := ((rep x).t2)::OutputForm;
                c: List OutputForm := [a, b];
                vconcat [hconcat [hspace 1, message("o")], hconcat [hspace 1, message("/"), hspace 1, message("\")], hconcat [a,hspace 3,b]]
        }
}
TreeClass: CombinatorialClassCategory == UnionClass(Atom, CrossClass(TreeClass, TreeClass)
) add;
aldor
   Compiling FriCAS source code from file 
      /var/zope2/var/LatexWiki/386348539091125073-25px001.as using 
      AXIOM-XL compiler and options 
-O -Fasy -Fao -Flsp -laxiom -Mno-AXL_W_WillObsolete -DAxiom -Y $AXIOM/algebra
      Use the system command )set compiler args to change these 
      options.
#1 (Warning) Deprecated message prefix: use `ALDOR_' instead of `_AXL'
   Compiling Lisp source code from file 
      ./386348539091125073-25px001.lsp
   Issuing )library command for 386348539091125073-25px001
   Reading /var/zope2/var/LatexWiki/386348539091125073-25px001.asy
   TreeClass is now explicitly exposed in frame initial 
   TreeClass will be automatically loaded when needed from 
      /var/zope2/var/LatexWiki/386348539091125073-25px001
   CombinatorialClassCategory is now explicitly exposed in frame 
      initial 
   CombinatorialClassCategory will be automatically loaded when needed 
      from /var/zope2/var/LatexWiki/386348539091125073-25px001
   UnionClass is now explicitly exposed in frame initial 
   UnionClass will be automatically loaded when needed from 
      /var/zope2/var/LatexWiki/386348539091125073-25px001
   Atom is now explicitly exposed in frame initial 
   Atom will be automatically loaded when needed from 
      /var/zope2/var/LatexWiki/386348539091125073-25px001
   CrossClass is now explicitly exposed in frame initial 
   CrossClass will be automatically loaded when needed from 
      /var/zope2/var/LatexWiki/386348539091125073-25px001
   Primitive is now explicitly exposed in frame initial 
   Primitive will be automatically loaded when needed from 
      /var/zope2/var/LatexWiki/386348539091125073-25px001
   Epsilon is now explicitly exposed in frame initial 
   Epsilon will be automatically loaded when needed from 
      /var/zope2/var/LatexWiki/386348539091125073-25px001axiom
[count(i)$TreeClass for i in 1..7]
Type: List Integer
axiom
)set output tex off
axiom
)set output algebra on
(list(5)$TreeClass)::List OutputForm
   (2)
   [        o        ,         o        ,         o        ,         o        ,
           / \                / \                / \                / \
              o                  o                  o                  o
             / \                / \                / \                / \
                o                  o            o       o            o
               / \                / \          / \     / \          / \
                  o              o                                     o
                 / \            / \                                   / \
            o        ,         o        ,         o        ,         o        ,
           / \                / \                / \                / \
              o          o         o        o         o          o         o
             / \        / \       / \      / \       / \        / \
/ \
            o                        o              o              o
           / \                      / \            / \            / \
          o
         / \
            o        ,         o        ,         o        ,         o        ,
           / \                / \                / \                / \
        o         o          o                  o                  o
       / \       / \        / \                / \                / \
      o                        o                  o            o       o
     / \                      / \                / \          / \     / \
                                 o              o
                                / \            / \
            o        ,         o        ]
           / \                / \
          o                  o
         / \                / \
        o                  o
       / \                / \
          o              o
         / \            / \