Miller/pattern unification in Agda
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

Higher-Order Pattern Unification in Agda

Higher-order unification problems can have multiple incompatible solutions, a challenge for many applications which can't afford to enumerate nor to guess, like type inference. A good strategy is instead to defer any decision except for the cases that fall into the pattern fragment, a subset which guarantees unique solutions.

This repo provides a formalization in Agda of higher-order pattern unification as defined by Miller in "A Logic Programming Language with Lambda-Abstraction, Function Variables, and Simple Unification".

The code has been tested with Agda-2.3.2 using The Agda standard library, if reloading you get an error related to "refl`" you need to invalidate the interface file for `Support.Equality' because of this bug with pattern synonyms.

The presentation is greatly influenced both by "Higher-Order Dynamic Pattern Unification for Dependent Types and Records" and "First-Order Unification by Structural Recursion" but neither are required to follow the work.

"A tutorial implementation of dynamic pattern unification" using Haskell and tackling a much more general version of the problem is a great introduction to the field.

The key to read the present work is to identify argument lists satisfying the pattern condition with injective renamings, this point of view and the richly typed structures make it very natural to apply concepts from category theory to design the algorithm and its proof of correctness.

Overview of the modules

- Definitions and Theorems from Category Theory.
 Category - monos, equalizers, pullbacks

- Variable Names as Typed de Bruijn Indexes.
 Vars            - `Γ ∋ τ'
   Vars.MatchTwo - matching against two names in one go
   Vars.SumIso   - `(Γ ++ Δ) ∋ τ' ≈ `Γ ∋ τ ⊎ Δ ∋ τ'

- Injective Renamings as a first-order datatype.
   Injections.Type - `Inj Γ Δ' ≈ injective `∀ τ → Γ ∋ τ → Δ ∋ τ'
   Injections.Sum  - `Inj Γ (Γ ++ Δ)' and `Inj Δ (Γ ++ Δ)'  

- Meta-Renamings send meta-vars to meta-vars applied to an injective renaming.
 MetaRens - MetaRen Γ Δ 

- Lambda Calculus Terms with and without the Pattern condition. 
   Syntax.Type             - `Tm< pat? > Σ Γ Δ τ', `ren' applies renamings `Inj Δ₀ Δ₁`
   Syntax.NbE              - Normalization by Evaluation
   Syntax.Sub              - `sub' applies meta-substitutions `Sub< pat? > Σ Γ₀ Γ₁`
   Syntax.Equality         - structural term equality, useful for recursing over its proofs
   Syntax.RenOrn           - `i ⁻¹ t' ≈ `∃ λ s → ren i s ≡ t' as an inductive type
   Syntax.OneHoleContext   - `wrap C t` plugs the term t into the hole of the context C 
   Syntax.No-Cycle         - `¬ ren i t ≡ wrap (d ∷ ds) (ren j t)' i.e. you can't go down 
                              a non-empty context and find the same term you started with

- Higher-Order Pattern Unification by Structural Recursion (well, almost).
 Unification                            - `Unify : (s t : Tm Sg G D T) → ∃σ-pat Max (Unifies s t) ⊎ ¬ ∃σ Unifies s t`
   Unification.Specification            - `Max (Unifies s t) σ` ≈ σ is the most general unifier of s and t
     Unification.Specification.Decr-Sub - `DSub Σ Γ Δ' ≈ substitutions decreasing the size of the context, or isomorphisms
   Unification.Injections               - equalizers and pullbacks
   Unification.MetaRens                 - coproducts, coequalizers and pushouts
   Unification.Pruning                  - solving for `ρ` in `ren i z ≡ sub ρ t`
     Unification.Pruning.Epi-Decr       - epic `MetaRen's, like `ρ' above, won't enlarge the context
   Unification.Inversion                - solving for `z` in `ren i z ≡ sub ρ t`
   Unification.OccursCheck              - checking whether a meta-var occurs in a term

- Wrappers around the Agda Standard Library.