use pattern_core::Pattern;
fn main() {
println!("=== Paramorphism Examples ===\n");
basic_sum();
depth_weighted_sum();
element_count_aggregation();
nesting_statistics();
structure_preserving_transformation();
}
fn basic_sum() {
println!("1. Basic Sum (equivalent to fold)");
println!(" Pattern: 10 with elements [5, 3]");
let p = Pattern::pattern(10, vec![Pattern::point(5), Pattern::point(3)]);
let para_sum: i32 = p.para(|pat, rs| *pat.value() + rs.iter().sum::<i32>());
let fold_sum: i32 = p.fold(0, |acc, v| acc + v);
println!(" Para sum: {}", para_sum);
println!(" Fold sum: {}", fold_sum);
println!(" Both produce: 18 (10 + 5 + 3)\n");
assert_eq!(para_sum, fold_sum);
}
fn depth_weighted_sum() {
println!("2. Depth-Weighted Sum");
println!(" Pattern: 10 with elements [5, 3]");
println!(" Formula: value * depth + sum(element_results)");
let p = Pattern::pattern(10, vec![Pattern::point(5), Pattern::point(3)]);
let depth_weighted: i32 = p.para(|pat, rs| {
let value = *pat.value();
let depth = pat.depth() as i32;
let element_sum: i32 = rs.iter().sum();
value * depth + element_sum
});
println!(" Root (depth=1): 10 * 1 = 10");
println!(" Leaves (depth=0): 5 * 0 = 0, 3 * 0 = 0");
println!(" Total: {}\n", depth_weighted);
assert_eq!(depth_weighted, 10);
}
fn element_count_aggregation() {
println!("3. Element-Count-Aware Aggregation");
println!(" Pattern: 10 with elements [pattern(5, [2]), 3]");
println!(" Formula: value * element_count + sum(element_results)");
let p = Pattern::pattern(
10,
vec![
Pattern::pattern(5, vec![Pattern::point(2)]),
Pattern::point(3),
],
);
let result: i32 = p.para(|pat, rs| {
let value = *pat.value();
let elem_count = pat.elements().len() as i32;
let element_sum: i32 = rs.iter().sum();
value * elem_count + element_sum
});
println!(" Root: 10 * 2 + (5 + 0) = 25");
println!(" Middle: 5 * 1 + 0 = 5");
println!(" Leaves: 2 * 0 = 0, 3 * 0 = 0");
println!(" Total: {}\n", result);
assert_eq!(result, 25);
}
fn nesting_statistics() {
println!("4. Nesting Statistics (sum, count, max_depth)");
println!(" Pattern: 1 with [pattern(2, [3]), 4]");
let p = Pattern::pattern(
1,
vec![
Pattern::pattern(2, vec![Pattern::point(3)]),
Pattern::point(4),
],
);
type Stats = (i32, usize, usize);
let (sum, count, max_depth): Stats = p.para(|pat, rs: &[Stats]| {
let value = *pat.value();
let depth = pat.depth();
let (child_sum, child_count, child_max_depth) = rs
.iter()
.fold((0_i32, 0_usize, 0_usize), |(s, c, d), (s2, c2, d2)| {
(s + s2, c + c2, d.max(*d2))
});
(
value + child_sum,
1 + child_count,
depth.max(child_max_depth),
)
});
println!(" Sum: {} (1 + 2 + 3 + 4)", sum);
println!(" Count: {} nodes", count);
println!(" Max depth: {}\n", max_depth);
assert_eq!(sum, 10);
assert_eq!(count, 4);
assert_eq!(max_depth, 2);
}
fn structure_preserving_transformation() {
println!("5. Structure-Preserving Transformation");
println!(" Pattern: 1 with [pattern(2, [3])]");
println!(" Transform: multiply each value by (depth + 1)");
let p = Pattern::pattern(1, vec![Pattern::pattern(2, vec![Pattern::point(3)])]);
let transformed: Pattern<i32> = p.para(|pat, rs: &[Pattern<i32>]| {
let value = *pat.value();
let depth = pat.depth() as i32;
let new_value = value * (depth + 1);
Pattern::pattern(new_value, rs.to_vec())
});
println!(" Original values: [1, 2, 3]");
println!(" Depths: [2, 1, 0]");
println!(" Transformed values: [3, 4, 3]");
println!(" Root: 1 * (2+1) = {}", transformed.value());
println!(
" First element: 2 * (1+1) = {}",
transformed.elements()[0].value()
);
println!(
" Leaf: 3 * (0+1) = {}\n",
transformed.elements()[0].elements()[0].value()
);
assert_eq!(*transformed.value(), 3);
assert_eq!(*transformed.elements()[0].value(), 4);
assert_eq!(*transformed.elements()[0].elements()[0].value(), 3);
}