| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Pattern.Reconcile
Description
Pattern reconciliation for normalizing duplicate identities.
This module provides operations to reconcile patterns by resolving duplicate identities and completing partial references. When patterns are parsed, streamed, or merged from multiple sources, the same identity may appear multiple times with different or evolving content. Reconciliation transforms such patterns into coherent ones where each identity appears exactly once.
Problem Statement
Currently nothing prevents the same identity from appearing multiple times with
different content in a Pattern v. This can arise from:
- Parsing gram notation with duplicate node definitions
- Streaming pattern updates where identities evolve over time
- Merging patterns from different sources
- References: atomic patterns pointing to fuller definitions elsewhere
Solution Overview
The reconcile operation normalizes patterns using configurable policies:
- **Collect**: Group all occurrences by identity
- **Reconcile**: Resolve duplicates according to policy
- **Rebuild**: Construct normalized pattern with each identity appearing once
Quick Start
>>>import Pattern.Core (Pattern(..), pattern, point)>>>import Pattern.Reconcile>>>import Subject.Core (Subject(..), Symbol(..))>>>>>>-- Reconcile with LastWriteWins policy>>>reconcile LastWriteWins patternWithDuplicates>>>>>>-- Get detailed report>>>let (result, report) = reconcileWithReport LastWriteWins pattern>>>reportDuplicatesFound report -- Number of duplicate identities
Reconciliation Policies
LastWriteWins- Keep the last occurrence of each identity. Useful for streaming updates where the most recent value is authoritative.
FirstWriteWins- Keep the first occurrence of each identity. Useful when initial definitions are authoritative.- Combine all occurrences using configurable strategies for structure (elements) and content (value).MergeelementStrategy valueStrategyStrict- Fail with detailed error if any duplicates have different content. Useful for validation and debugging.
Synopsis
- class Ord i => HasIdentity v i | v -> i where
- identity :: v -> i
- class Mergeable v where
- type MergeStrategy v
- merge :: MergeStrategy v -> v -> v -> v
- class Refinable v where
- isRefinementOf :: v -> v -> Bool
- data ReconciliationPolicy s
- data ElementMergeStrategy
- data SubjectMergeStrategy = SubjectMergeStrategy {}
- data LabelMerge
- data PropertyMerge
- defaultSubjectMergeStrategy :: SubjectMergeStrategy
- data Conflict i v = Conflict {
- conflictId :: i
- conflictExisting :: v
- conflictIncoming :: v
- conflictLocations :: [Path]
- data ReconcileError i v = ReconcileError {
- errorMessage :: String
- errorConflicts :: [Conflict i v]
- data ReconcileReport i = ReconcileReport {}
- type Path = [Int]
- reconcile :: (HasIdentity v i, Mergeable v, Refinable v, Eq v) => ReconciliationPolicy (MergeStrategy v) -> Pattern v -> Either (ReconcileError i v) (Pattern v)
- reconcileWithReport :: (HasIdentity v i, Mergeable v, Refinable v, Eq v) => ReconciliationPolicy (MergeStrategy v) -> Pattern v -> (Either (ReconcileError i v) (Pattern v), ReconcileReport i)
- needsReconciliation :: HasIdentity v i => Pattern v -> Bool
- findConflicts :: (HasIdentity v i, Eq v) => Pattern v -> [Conflict i v]
- collectByIdentity :: HasIdentity v i => Pattern v -> Map i [(Pattern v, Path)]
- isReference :: (HasIdentity v i, Refinable v) => Pattern v -> Map i (Pattern v) -> Bool
Core Abstractions
class Ord i => HasIdentity v i | v -> i where Source #
Allows extracting a unique identifier from a value.
class Mergeable v where Source #
Allows merging two values according to a strategy.
Methods
merge :: MergeStrategy v -> v -> v -> v Source #
Merge two values. The first value is the "accumulated" or "existing" one, the second is the "incoming" one.
Instances
| Mergeable Subject Source # | |||||
Defined in Pattern.Reconcile Associated Types
| |||||
class Refinable v where Source #
Allows checking if one value is a "partial" version of another.
Methods
isRefinementOf :: v -> v -> Bool Source #
Returns True if sub contains a subset of the information in sup.
Used to detect if an atomic pattern is a reference to a full definition.
Reconciliation Policies
data ReconciliationPolicy s Source #
Policy for resolving duplicate identities during reconciliation.
When a pattern contains the same identity multiple times (determined by
comparing identity values), a reconciliation policy determines how to
combine or choose between the duplicate occurrences.
The type parameter s is the value-specific merge strategy (e.g., SubjectMergeStrategy).
Constructors
| LastWriteWins | Keep the last occurrence of each identity. Useful for streaming updates where the most recent value is authoritative. |
| FirstWriteWins | Keep the first occurrence of each identity. Useful when initial definitions are authoritative and later ones are ignored. |
| Merge ElementMergeStrategy s | Combine all occurrences using specified strategies for elements and values. |
| Strict | Fail if any duplicate identities have different content. |
Instances
data ElementMergeStrategy Source #
Strategy for merging the children (elements) of a pattern.
Constructors
| ReplaceElements | Later element list completely replaces earlier ones. |
| AppendElements | Concatenate all element lists in traversal order. |
| UnionElements | Deduplicate elements by identity. |
Instances
| Generic ElementMergeStrategy Source # | |||||
Defined in Pattern.Reconcile Associated Types
Methods from :: ElementMergeStrategy -> Rep ElementMergeStrategy x # to :: Rep ElementMergeStrategy x -> ElementMergeStrategy # | |||||
| Show ElementMergeStrategy Source # | |||||
Defined in Pattern.Reconcile Methods showsPrec :: Int -> ElementMergeStrategy -> ShowS # show :: ElementMergeStrategy -> String # showList :: [ElementMergeStrategy] -> ShowS # | |||||
| Eq ElementMergeStrategy Source # | |||||
Defined in Pattern.Reconcile Methods (==) :: ElementMergeStrategy -> ElementMergeStrategy -> Bool # (/=) :: ElementMergeStrategy -> ElementMergeStrategy -> Bool # | |||||
| type Rep ElementMergeStrategy Source # | |||||
Defined in Pattern.Reconcile type Rep ElementMergeStrategy = D1 ('MetaData "ElementMergeStrategy" "Pattern.Reconcile" "pattern-0.4.0.0-inplace" 'False) (C1 ('MetaCons "ReplaceElements" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "AppendElements" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "UnionElements" 'PrefixI 'False) (U1 :: Type -> Type))) | |||||
data SubjectMergeStrategy Source #
Strategy for merging Subject content.
Constructors
| SubjectMergeStrategy | |
Fields | |
Instances
| Generic SubjectMergeStrategy Source # | |||||
Defined in Pattern.Reconcile Associated Types
Methods from :: SubjectMergeStrategy -> Rep SubjectMergeStrategy x # to :: Rep SubjectMergeStrategy x -> SubjectMergeStrategy # | |||||
| Show SubjectMergeStrategy Source # | |||||
Defined in Pattern.Reconcile Methods showsPrec :: Int -> SubjectMergeStrategy -> ShowS # show :: SubjectMergeStrategy -> String # showList :: [SubjectMergeStrategy] -> ShowS # | |||||
| Eq SubjectMergeStrategy Source # | |||||
Defined in Pattern.Reconcile Methods (==) :: SubjectMergeStrategy -> SubjectMergeStrategy -> Bool # (/=) :: SubjectMergeStrategy -> SubjectMergeStrategy -> Bool # | |||||
| type Rep SubjectMergeStrategy Source # | |||||
Defined in Pattern.Reconcile type Rep SubjectMergeStrategy = D1 ('MetaData "SubjectMergeStrategy" "Pattern.Reconcile" "pattern-0.4.0.0-inplace" 'False) (C1 ('MetaCons "SubjectMergeStrategy" 'PrefixI 'True) (S1 ('MetaSel ('Just "labelMerge") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 LabelMerge) :*: S1 ('MetaSel ('Just "propertyMerge") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 PropertyMerge))) | |||||
data LabelMerge Source #
Constructors
| UnionLabels | |
| IntersectLabels | |
| ReplaceLabels |
Instances
| Generic LabelMerge Source # | |||||
Defined in Pattern.Reconcile Associated Types
| |||||
| Show LabelMerge Source # | |||||
Defined in Pattern.Reconcile Methods showsPrec :: Int -> LabelMerge -> ShowS # show :: LabelMerge -> String # showList :: [LabelMerge] -> ShowS # | |||||
| Eq LabelMerge Source # | |||||
Defined in Pattern.Reconcile | |||||
| type Rep LabelMerge Source # | |||||
Defined in Pattern.Reconcile type Rep LabelMerge = D1 ('MetaData "LabelMerge" "Pattern.Reconcile" "pattern-0.4.0.0-inplace" 'False) (C1 ('MetaCons "UnionLabels" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "IntersectLabels" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "ReplaceLabels" 'PrefixI 'False) (U1 :: Type -> Type))) | |||||
data PropertyMerge Source #
Constructors
| ReplaceProperties | |
| ShallowMerge | |
| DeepMerge |
Instances
| Generic PropertyMerge Source # | |||||
Defined in Pattern.Reconcile Associated Types
| |||||
| Show PropertyMerge Source # | |||||
Defined in Pattern.Reconcile Methods showsPrec :: Int -> PropertyMerge -> ShowS # show :: PropertyMerge -> String # showList :: [PropertyMerge] -> ShowS # | |||||
| Eq PropertyMerge Source # | |||||
Defined in Pattern.Reconcile Methods (==) :: PropertyMerge -> PropertyMerge -> Bool # (/=) :: PropertyMerge -> PropertyMerge -> Bool # | |||||
| type Rep PropertyMerge Source # | |||||
Defined in Pattern.Reconcile type Rep PropertyMerge = D1 ('MetaData "PropertyMerge" "Pattern.Reconcile" "pattern-0.4.0.0-inplace" 'False) (C1 ('MetaCons "ReplaceProperties" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "ShallowMerge" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "DeepMerge" 'PrefixI 'False) (U1 :: Type -> Type))) | |||||
defaultSubjectMergeStrategy :: SubjectMergeStrategy Source #
Default merge strategy for Subjects.
Error and Report Types
Constructors
| Conflict | |
Fields
| |
Instances
| Generic (Conflict i v) Source # | |||||
Defined in Pattern.Reconcile Associated Types
| |||||
| (Show i, Show v) => Show (Conflict i v) Source # | |||||
| (Eq i, Eq v) => Eq (Conflict i v) Source # | |||||
| type Rep (Conflict i v) Source # | |||||
Defined in Pattern.Reconcile type Rep (Conflict i v) = D1 ('MetaData "Conflict" "Pattern.Reconcile" "pattern-0.4.0.0-inplace" 'False) (C1 ('MetaCons "Conflict" 'PrefixI 'True) ((S1 ('MetaSel ('Just "conflictId") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 i) :*: S1 ('MetaSel ('Just "conflictExisting") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 v)) :*: (S1 ('MetaSel ('Just "conflictIncoming") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 v) :*: S1 ('MetaSel ('Just "conflictLocations") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 [Path])))) | |||||
data ReconcileError i v Source #
Constructors
| ReconcileError | |
Fields
| |
Instances
| Generic (ReconcileError i v) Source # | |||||
Defined in Pattern.Reconcile Associated Types
Methods from :: ReconcileError i v -> Rep (ReconcileError i v) x # to :: Rep (ReconcileError i v) x -> ReconcileError i v # | |||||
| (Show i, Show v) => Show (ReconcileError i v) Source # | |||||
Defined in Pattern.Reconcile Methods showsPrec :: Int -> ReconcileError i v -> ShowS # show :: ReconcileError i v -> String # showList :: [ReconcileError i v] -> ShowS # | |||||
| (Eq i, Eq v) => Eq (ReconcileError i v) Source # | |||||
Defined in Pattern.Reconcile Methods (==) :: ReconcileError i v -> ReconcileError i v -> Bool # (/=) :: ReconcileError i v -> ReconcileError i v -> Bool # | |||||
| type Rep (ReconcileError i v) Source # | |||||
Defined in Pattern.Reconcile type Rep (ReconcileError i v) = D1 ('MetaData "ReconcileError" "Pattern.Reconcile" "pattern-0.4.0.0-inplace" 'False) (C1 ('MetaCons "ReconcileError" 'PrefixI 'True) (S1 ('MetaSel ('Just "errorMessage") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 String) :*: S1 ('MetaSel ('Just "errorConflicts") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 [Conflict i v]))) | |||||
data ReconcileReport i Source #
Constructors
| ReconcileReport | |
Fields | |
Instances
| Generic (ReconcileReport i) Source # | |||||
Defined in Pattern.Reconcile Associated Types
Methods from :: ReconcileReport i -> Rep (ReconcileReport i) x # to :: Rep (ReconcileReport i) x -> ReconcileReport i # | |||||
| Show i => Show (ReconcileReport i) Source # | |||||
Defined in Pattern.Reconcile Methods showsPrec :: Int -> ReconcileReport i -> ShowS # show :: ReconcileReport i -> String # showList :: [ReconcileReport i] -> ShowS # | |||||
| Eq i => Eq (ReconcileReport i) Source # | |||||
Defined in Pattern.Reconcile Methods (==) :: ReconcileReport i -> ReconcileReport i -> Bool # (/=) :: ReconcileReport i -> ReconcileReport i -> Bool # | |||||
| type Rep (ReconcileReport i) Source # | |||||
Defined in Pattern.Reconcile type Rep (ReconcileReport i) = D1 ('MetaData "ReconcileReport" "Pattern.Reconcile" "pattern-0.4.0.0-inplace" 'False) (C1 ('MetaCons "ReconcileReport" 'PrefixI 'True) ((S1 ('MetaSel ('Just "reportDuplicatesFound") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int) :*: S1 ('MetaSel ('Just "reportReferencesResolved") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int)) :*: (S1 ('MetaSel ('Just "reportMergesPerformed") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 Int) :*: S1 ('MetaSel ('Just "reportSubjectCounts") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Map i Int))))) | |||||
Reconciliation Operations
reconcile :: (HasIdentity v i, Mergeable v, Refinable v, Eq v) => ReconciliationPolicy (MergeStrategy v) -> Pattern v -> Either (ReconcileError i v) (Pattern v) Source #
reconcileWithReport :: (HasIdentity v i, Mergeable v, Refinable v, Eq v) => ReconciliationPolicy (MergeStrategy v) -> Pattern v -> (Either (ReconcileError i v) (Pattern v), ReconcileReport i) Source #
Inspection
needsReconciliation :: HasIdentity v i => Pattern v -> Bool Source #
findConflicts :: (HasIdentity v i, Eq v) => Pattern v -> [Conflict i v] Source #
collectByIdentity :: HasIdentity v i => Pattern v -> Map i [(Pattern v, Path)] Source #
Utilities
isReference :: (HasIdentity v i, Refinable v) => Pattern v -> Map i (Pattern v) -> Bool Source #