Expand description
pattern-core - Core pattern data structures
This crate provides the core pattern data structures for the pattern-rs library. It is a faithful port of the gram-hs reference implementation.
§Overview
The pattern-core crate defines two main types:
-
Pattern<V>: A recursive, nested structure (s-expression-like) that is generic over value typeV. This is the foundational data structure for representing nested, hierarchical data that may be interpreted as graphs. -
Subject: A self-descriptive value type with identity, labels, and properties. Designed to be used as the value type inPattern<Subject>, which is a common use case for replacing object-graphs with nested patterns.
§Quick Start
use pattern_core::{Pattern, Subject, Symbol, Value};
use std::collections::{HashSet, HashMap};
// Create an atomic pattern (special case)
let atomic = Pattern::point("hello".to_string());
// Create a pattern with elements (primary constructor)
let pattern = Pattern::pattern("parent".to_string(), vec![
Pattern::point("child1".to_string()),
Pattern::point("child2".to_string()),
]);
// Access pattern components
assert_eq!(atomic.value(), "hello");
assert_eq!(pattern.length(), 2);
assert_eq!(pattern.depth(), 1);
// Transform pattern values (Functor)
let upper = pattern.clone().map(|s| s.to_uppercase());
assert_eq!(upper.value(), "PARENT");
// Validate pattern structure
use pattern_core::ValidationRules;
let rules = ValidationRules {
max_depth: Some(10),
..Default::default()
};
assert!(pattern.validate(&rules).is_ok());
// Analyze pattern structure
let analysis = pattern.analyze_structure();
println!("Structure: {}", analysis.summary);
// Create a pattern with Subject value
let subject = Subject {
identity: Symbol("n".to_string()),
labels: {
let mut s = HashSet::new();
s.insert("Person".to_string());
s
},
properties: {
let mut m = HashMap::new();
m.insert("name".to_string(), Value::VString("Alice".to_string()));
m
},
};
let pattern_with_subject: Pattern<Subject> = Pattern::point(subject);§Pattern Combination
Patterns can be combined associatively using the combine() method when the value type
implements the Combinable trait. Combination merges two patterns by combining their values
and concatenating their elements.
use pattern_core::{Pattern, Combinable};
// Combine atomic patterns (no elements)
let p1 = Pattern::point("hello".to_string());
let p2 = Pattern::point(" world".to_string());
let combined = p1.combine(p2);
assert_eq!(combined.value(), "hello world");
assert_eq!(combined.length(), 0);
// Combine patterns with elements
let p3 = Pattern::pattern("a".to_string(), vec![
Pattern::point("b".to_string()),
Pattern::point("c".to_string()),
]);
let p4 = Pattern::pattern("d".to_string(), vec![
Pattern::point("e".to_string()),
]);
let result = p3.combine(p4);
assert_eq!(result.value(), "ad");
assert_eq!(result.length(), 3); // [b, c, e]
// Associativity: (a ⊕ b) ⊕ c = a ⊕ (b ⊕ c)
let a = Pattern::point("a".to_string());
let b = Pattern::point("b".to_string());
let c = Pattern::point("c".to_string());
let left = a.clone().combine(b.clone()).combine(c.clone());
let right = a.combine(b.combine(c));
assert_eq!(left, right);§Pattern Ordering
Patterns implement Ord and PartialOrd for types that support ordering,
enabling sorting, comparison, and use in ordered data structures.
use pattern_core::Pattern;
use std::collections::{BTreeSet, BTreeMap};
// Compare patterns
let p1 = Pattern::point(1);
let p2 = Pattern::point(2);
assert!(p1 < p2);
// Value-first ordering: values compared before elements
let p3 = Pattern::pattern(3, vec![Pattern::point(100)]);
let p4 = Pattern::pattern(4, vec![Pattern::point(1)]);
assert!(p3 < p4); // 3 < 4, elements not compared
// Sort patterns
let mut patterns = vec![
Pattern::point(5),
Pattern::point(2),
Pattern::point(8),
];
patterns.sort();
assert_eq!(patterns[0], Pattern::point(2));
// Find min/max
let min = patterns.iter().min().unwrap();
let max = patterns.iter().max().unwrap();
assert_eq!(min, &Pattern::point(2));
assert_eq!(max, &Pattern::point(8));
// Use in BTreeSet (maintains sorted order)
let mut set = BTreeSet::new();
set.insert(Pattern::point(5));
set.insert(Pattern::point(2));
set.insert(Pattern::point(8));
let sorted: Vec<_> = set.iter().map(|p| p.value).collect();
assert_eq!(sorted, vec![2, 5, 8]);
// Use as BTreeMap keys
let mut map = BTreeMap::new();
map.insert(Pattern::point(1), "first");
map.insert(Pattern::point(2), "second");
assert_eq!(map.get(&Pattern::point(1)), Some(&"first"));§WASM Compatibility
All types in this crate are fully compatible with WebAssembly targets. Compile for WASM with:
cargo build --package pattern-core --target wasm32-unknown-unknown§Reference Implementation
This crate is ported from the gram-hs reference implementation:
- Pattern:
../pattern-hs/libs/pattern/src/Pattern.hs - Subject:
../pattern-hs/libs/subject/src/Subject/Core.hs - Feature Spec:
../pattern-hs/specs/001-pattern-data-structure/
Re-exports§
pub use graph::all_paths;pub use graph::betweenness_centrality;pub use graph::bfs;pub use graph::canonical_classifier;pub use graph::classify_by_shape;pub use graph::connected_components;pub use graph::degree_centrality;pub use graph::dfs;pub use graph::directed;pub use graph::directed_reverse;pub use graph::filter_graph;pub use graph::fold_graph;pub use graph::frame_query;pub use graph::from_graph_lens;pub use graph::from_pattern_graph;pub use graph::from_test_node;pub use graph::has_cycle;pub use graph::has_path;pub use graph::is_connected;pub use graph::is_neighbor;pub use graph::map_all_graph;pub use graph::map_graph;pub use graph::map_with_context;pub use graph::materialize;pub use graph::memoize_incident_rels;pub use graph::minimum_spanning_tree;pub use graph::para_graph;pub use graph::para_graph_fixed;pub use graph::query_annotations_of;pub use graph::query_co_members;pub use graph::query_walks_containing;pub use graph::shortest_path;pub use graph::topological_sort;pub use graph::undirected;pub use graph::unfold_graph;pub use graph::unfold_graph;pub use graph::CategoryMappers;pub use graph::GraphClass;pub use graph::GraphClassifier;pub use graph::GraphQuery;pub use graph::GraphValue;pub use graph::GraphView;pub use graph::Substitution;pub use graph::TraversalDirection;pub use graph::TraversalWeight;pub use pattern::unfold;pub use pattern::unfold;pub use pattern::Pattern;pub use pattern::StructureAnalysis;pub use pattern::ValidationError;pub use pattern::ValidationRules;pub use pattern_graph::from_pattern_graph as graph_query_from_pattern_graph;pub use pattern_graph::from_patterns;pub use pattern_graph::from_patterns_with_policy;pub use pattern_graph::merge as pg_merge;pub use pattern_graph::merge_with_policy as pg_merge_with_policy;pub use pattern_graph::PatternGraph;pub use reconcile::ElementMergeStrategy;pub use reconcile::HasIdentity;pub use reconcile::LabelMerge;pub use reconcile::Mergeable;pub use reconcile::PropertyMerge;pub use reconcile::ReconciliationPolicy;pub use reconcile::Refinable;pub use reconcile::SubjectMergeStrategy;pub use subject::PropertyRecord;pub use subject::RangeValue;pub use subject::Subject;pub use subject::Symbol;pub use subject::Value;
Modules§
- graph
- pattern
- pattern_
graph - PatternGraph: typed container for nodes, relationships, walks, and annotations.
- reconcile
- Pattern reconciliation for normalizing duplicate identities.
- subject
- Subject type definition
- test_
utils - Test utilities for pattern testing infrastructure
Structs§
- Empty
Subject - Newtype wrapper for “empty” combination strategy that creates anonymous subjects.
- First
Subject - Newtype wrapper for “first wins” combination strategy.
- Last
Subject - Newtype wrapper for “last wins” combination strategy.
Traits§
- Combinable
- Types that support associative combination.