pattern_core/graph/transform/unfold_graph.rs
1//! unfold_graph: build a PatternGraph from seeds using an expander function.
2//!
3//! Ported from `Pattern.Graph.Transform.unfoldGraph` in the Haskell reference.
4
5use crate::graph::graph_classifier::{GraphClassifier, GraphValue};
6use crate::pattern::Pattern;
7use crate::pattern_graph::{from_patterns_with_policy, PatternGraph};
8use crate::reconcile::{HasIdentity, Mergeable, ReconciliationPolicy, Refinable};
9use crate::subject::Symbol;
10
11/// Build a `PatternGraph` from a list of seeds.
12///
13/// For each seed, `expand` returns a list of `Pattern<V>` to insert into the graph.
14/// All patterns from all seeds are collected and inserted using the given classifier
15/// and reconciliation policy.
16///
17/// # Examples
18///
19/// ```rust
20/// use pattern_core::{unfold_graph, canonical_classifier, Pattern, Subject, Symbol, Value};
21/// use pattern_core::reconcile::ReconciliationPolicy;
22/// use std::collections::{HashSet, HashMap};
23///
24/// let classifier = canonical_classifier();
25/// let policy = ReconciliationPolicy::LastWriteWins;
26///
27/// struct Row { id: &'static str }
28///
29/// let rows = vec![Row { id: "a" }, Row { id: "b" }];
30/// let graph = unfold_graph(
31/// &classifier,
32/// &policy,
33/// |row: Row| vec![Pattern::point(Subject {
34/// identity: Symbol(row.id.to_string()),
35/// labels: HashSet::new(),
36/// properties: HashMap::new(),
37/// })],
38/// rows,
39/// );
40///
41/// assert_eq!(graph.pg_nodes.len(), 2);
42/// ```
43pub fn unfold_graph<A, Extra, V>(
44 classifier: &GraphClassifier<Extra, V>,
45 policy: &ReconciliationPolicy<V::MergeStrategy>,
46 expand: impl Fn(A) -> Vec<Pattern<V>>,
47 seeds: Vec<A>,
48) -> PatternGraph<Extra, V>
49where
50 V: GraphValue<Id = Symbol>
51 + HasIdentity<V, Symbol>
52 + Mergeable
53 + Refinable
54 + PartialEq
55 + Clone
56 + 'static,
57 Extra: 'static,
58{
59 let patterns: Vec<Pattern<V>> = seeds.into_iter().flat_map(expand).collect();
60 from_patterns_with_policy(classifier, policy, patterns)
61}