| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Pattern.Graph.Transform
Description
Graph transformation operations over GraphView.
This module provides bulk transformation, filtering, folding, and
iterative shape-aware algorithms for graphs represented as GraphView.
Overview
Transformations operate lazily over GraphView and are composed by
function composition. Finalize a pipeline by calling materialize.
Elements are classified by shape (via classifyByShape) into five buckets:
GNode, GRelationship, GWalk, GAnnotation, and GOther. The
topoShapeSort function orders elements within a GraphView so that
each element is processed after all elements it structurally depends on.
Example
pipeline :: PatternGraph Subject -> PatternGraph Subject pipeline graph = Pattern.PatternGraph.materialize canonicalClassifier LastWriteWins . mapWithContext canonicalClassifier enrich . filterGraph canonicalClassifier isRelevant dissolve . mapAllGraph updateTimestamp . Pattern.PatternGraph.toGraphView canonicalClassifier $ graph
Synopsis
- unfoldGraph :: (GraphValue v, Eq v, Mergeable v, HasIdentity v (Id v), Refinable v) => GraphClassifier extra v -> ReconciliationPolicy (MergeStrategy v) -> (a -> [Pattern v]) -> [a] -> PatternGraph extra v
- mapGraph :: GraphClassifier extra v -> (Pattern v -> Pattern v) -> (Pattern v -> Pattern v) -> (Pattern v -> Pattern v) -> (Pattern v -> Pattern v) -> (Pattern v -> Pattern v) -> GraphView extra v -> GraphView extra v
- mapAllGraph :: (Pattern v -> Pattern v) -> GraphView extra v -> GraphView extra v
- filterGraph :: GraphClassifier extra v -> (GraphClass extra -> Pattern v -> Bool) -> Substitution v -> GraphView extra v -> GraphView extra v
- foldGraph :: Monoid m => (GraphClass extra -> Pattern v -> m) -> GraphView extra v -> m
- mapWithContext :: GraphClassifier extra v -> (GraphQuery v -> Pattern v -> Pattern v) -> GraphView extra v -> GraphView extra v
- scopeDictFromGraphView :: GraphValue v => GraphView extra v -> ScopeDict (Id v) v
- paraGraph :: GraphValue v => (GraphQuery v -> Pattern v -> [r] -> r) -> GraphView extra v -> Map (Id v) r
- paraGraphFixed :: (GraphValue v, Ord (Id v)) => (r -> r -> Bool) -> (GraphQuery v -> Pattern v -> [r] -> r) -> r -> GraphView extra v -> Map (Id v) r
Graph construction from seeds
unfoldGraph :: (GraphValue v, Eq v, Mergeable v, HasIdentity v (Id v), Refinable v) => GraphClassifier extra v -> ReconciliationPolicy (MergeStrategy v) -> (a -> [Pattern v]) -> [a] -> PatternGraph extra v Source #
Build a PatternGraph by expanding seed values into patterns and merging.
Each seed is expanded into a list of 'Pattern v' via the provided function.
All resulting patterns are merged into a single PatternGraph using the
given reconciliation policy.
Example
rowToPatterns :: Row -> [Pattern Subject] rowToPatterns row = [ personNode row, departmentNode row, worksInRel row ] etlGraph = unfoldGraph canonicalClassifier LastWriteWins rowToPatterns rows
Bulk transformations
Arguments
| :: GraphClassifier extra v | |
| -> (Pattern v -> Pattern v) | nodes |
| -> (Pattern v -> Pattern v) | relationships |
| -> (Pattern v -> Pattern v) | walks |
| -> (Pattern v -> Pattern v) | annotations |
| -> (Pattern v -> Pattern v) | other / unrecognized |
| -> GraphView extra v | |
| -> GraphView extra v |
Map over view elements, applying a different function per GraphClass.
Each element in viewElements is transformed by the function corresponding
to its category. The viewQuery is passed through unchanged.
mapAllGraph :: (Pattern v -> Pattern v) -> GraphView extra v -> GraphView extra v Source #
Apply a single function uniformly to every element in the view.
filterGraph :: GraphClassifier extra v -> (GraphClass extra -> Pattern v -> Bool) -> Substitution v -> GraphView extra v -> GraphView extra v Source #
Filter elements from a GraphView, repairing container gaps via Substitution.
Elements that do not satisfy the predicate are removed. Container structures
(walks, annotations) whose internal elements are removed are repaired
according to the Substitution strategy.
foldGraph :: Monoid m => (GraphClass extra -> Pattern v -> m) -> GraphView extra v -> m Source #
Reduce all view elements into a single Monoid accumulation.
Context-aware enrichment
mapWithContext :: GraphClassifier extra v -> (GraphQuery v -> Pattern v -> Pattern v) -> GraphView extra v -> GraphView extra v Source #
Map over view elements with access to the original snapshot GraphQuery.
The mapping function receives the unmodified query from the original view, ensuring deterministic snapshot semantics: later elements do not see mutations applied to earlier elements.
Iterative topology-aware algorithms
scopeDictFromGraphView :: GraphValue v => GraphView extra v -> ScopeDict (Id v) v Source #
Reify the generic scope answers for a GraphView snapshot.
This exposes the unified scope model without exporting the internal adapter type used to compute it.
Invariants:
allElementscovers every classified element in theGraphView.byIdentityis bounded to that snapshot.containersandsiblingsare derived from direct containment only.- Duplicate graph identities are rejected when reifying generic scope
answers, because
ScopeQuerylookup is keyed only by 'Id v'.
Example:
let scope = scopeDictFromGraphView view length (allElements scope)
paraGraph :: GraphValue v => (GraphQuery v -> Pattern v -> [r] -> r) -> GraphView extra v -> Map (Id v) r Source #
Single-pass structure-aware fold over a GraphView.
Elements are processed in containment order via topoShapeSort:
each element receives already-computed results for its direct sub-elements.
Processing Order
Determined by topoShapeSort:
- Nodes (atomic — no sub-elements)
- Relationships (contain nodes)
- Walks (contain relationships)
- Annotations (contain any element type, including other annotations)
- Other (GOther — unconstrained sub-elements)
Within the Annotation and Other buckets, elements are additionally sorted so that referenced elements appear before the elements that reference them.
The subResults Contract
The [r] argument received by f contains the results of all direct
sub-elements of the current element that have already been processed.
If a sub-element has not yet been processed — which can occur when a
dependency cycle exists within a bucket — its result is omitted from
subResults. The list will be shorter than elements p. Callers
should treat subResults as a best-effort list, not a guaranteed
complete list.
Example
-- Count the number of sub-results (i.e., direct dependencies) for each element countDeps :: GraphValue v => GraphView extra v -> Map (Id v) Int countDeps = paraGraph (\_ _ subResults -> length subResults)
paraGraphFixed :: (GraphValue v, Ord (Id v)) => (r -> r -> Bool) -> (GraphQuery v -> Pattern v -> [r] -> r) -> r -> GraphView extra v -> Map (Id v) r Source #
Iterate paraGraph rounds until the convergence predicate is satisfied.
Each round applies topoShapeSort to ensure correct within-bucket
dependency ordering. The ordering is recomputed identically every round
(the GraphView is immutable).
See paraGraph for the subResults contract, including cycle behaviour.
The convergence predicate conv old new should return True when the
result is considered stable. A common example for floating-point algorithms:
\old new -> abs (old - new) < 0.0001
The initial value r0 is used for all elements in the first round.