rewriting.lagda.rst 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. .. _rewriting:
  2. *********
  3. Rewriting
  4. *********
  5. Rewrite rules allow you to extend Agda's evaluation relation with new
  6. computation rules.
  7. .. note:: This page is about the :option:`--rewriting` option and the
  8. associated :ref:`REWRITE <builtin-rewrite>` builtin. You might be
  9. looking for the documentation on the :ref:`rewrite construct
  10. <with-rewrite>` instead.
  11. Rewrite rules by example
  12. ------------------------
  13. To enable rewrite rules, you should run Agda with the flag ``--rewriting`` and import the modules ``Agda.Builtin.Equality`` and ``Agda.Builtin.Equality.Rewrite``:
  14. ::
  15. {-# OPTIONS --rewriting #-}
  16. module language.rewriting where
  17. open import Agda.Builtin.Equality
  18. open import Agda.Builtin.Equality.Rewrite
  19. ..
  20. ::
  21. open import Agda.Builtin.Nat
  22. variable
  23. A B C : Set
  24. x y z : A
  25. k l m n : Nat
  26. cong : (f : A → B) → x ≡ y → f x ≡ f y
  27. cong f refl = refl
  28. transport : (P : A → Set) → x ≡ y → P x → P y
  29. transport P refl p = p
  30. Overlapping pattern matching
  31. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  32. To start, let's look at an example where rewrite rules can solve a
  33. problem that is encountered by almost every newcomer to Agda. This
  34. problem usually pops up as the question why ``0 + m`` computes to
  35. ``m``, but ``m + 0`` does not (and similarly, ``(suc m) + n`` computes
  36. to ``suc (m + n)`` but ``m + (suc n)`` does not). This problem
  37. manifests itself for example when trying to prove commutativity of ``_+_``:
  38. .. code-block:: agda
  39. +comm : m + n ≡ n + m
  40. +comm {m = zero} = refl
  41. +comm {m = suc m} = cong suc (+comm {m = m})
  42. Here, Agda complains that ``n != n + zero of type Nat``. The usual way
  43. to solve this problem is by proving the equations ``m + 0 ≡ m`` and
  44. ``m + (suc n) ≡ suc (m + n)`` and using an explicit ``rewrite``
  45. statement in the main proof (N.B.: Agda's ``rewrite`` keyword should not
  46. be confused with rewrite rules, which are added by a ``REWRITE``
  47. pragma.)
  48. By using rewrite rules, we can simulate the solution from our
  49. paper. First, we need to prove that the equations we want hold as
  50. propositional equalities:
  51. ::
  52. +zero : m + zero ≡ m
  53. +zero {m = zero} = refl
  54. +zero {m = suc m} = cong suc +zero
  55. +suc : m + (suc n) ≡ suc (m + n)
  56. +suc {m = zero} = refl
  57. +suc {m = suc m} = cong suc +suc
  58. Next we mark the equalities as rewrite rules with a ``REWRITE`` pragma:
  59. ::
  60. {-# REWRITE +zero +suc #-}
  61. Now the proof of commutativity works exactly as we wrote it before:
  62. ::
  63. +comm : m + n ≡ n + m
  64. +comm {m = zero} = refl
  65. +comm {m = suc m} = cong suc (+comm {m = m})
  66. Note that there is no way to make this proof go through without
  67. rewrite rules: it is essential that ``_+_`` computes both on its first
  68. and its second argument, but there's no way to define ``_+_`` in such a
  69. way using Agda's regular pattern matching.
  70. More examples
  71. ~~~~~~~~~~~~~
  72. Additional examples of how to use rewrite rules can be found in `a
  73. blog post by Jesper Cockx
  74. <https://jesper.sikanda.be/posts/hack-your-type-theory.html>`__.
  75. General shape of rewrite rules
  76. ------------------------------
  77. In general, an equality proof ``eq`` may be registered as a rewrite
  78. rule using the pragma ``{-# REWRITE eq #-}``, provided the following
  79. requirements are met:
  80. * The type of ``eq`` is of the form ``eq : (x₁ : A₁) ... (xₖ : Aₖ) → f p₁ ... pₙ ≡ v``
  81. * ``f`` is a postulate, a defined function symbol, or a constructor
  82. applied to fully general parameters (i.e. the parameters must be
  83. distinct variables)
  84. * Each variable ``x₁``, ..., ``xₖ`` occurs at least once in a pattern
  85. position in ``p₁ ... pₙ`` (see below for the definition of pattern
  86. positions)
  87. * The left-hand side ``f p₁ ... pₙ`` should be neutral, i.e. it should
  88. not reduce.
  89. The following patterns are supported:
  90. * ``x y₁ ... yₙ``, where ``x`` is a pattern variable and ``y₁``, ...,
  91. ``yₙ`` are distinct variables that are bound locally in the pattern
  92. * ``f p₁ ... pₙ``, where ``f`` is a postulate, a defined function, a
  93. constructor, or a data/record type, and ``p₁``, ..., ``pₙ`` are
  94. again patterns
  95. * ``λ x → p``, where ``p`` is again a pattern
  96. * ``(x : P) → Q``, where ``P`` and ``Q`` are again patterns
  97. * ``y p₁ ... pₙ``, where ``y`` is a variable bound locally in the
  98. pattern and ``p₁``, ..., ``pₙ`` are again patterns
  99. * ``Set p`` or ``Prop p``, where ``p`` is again a pattern
  100. * Any other term ``v`` (here the variables in ``v`` are not considered
  101. to be in a pattern position)
  102. Once a rewrite rule has been added, Agda automatically rewrites all
  103. instances of the left-hand side to the corresponding instance of the
  104. right-hand side during reduction. More precisely, a term
  105. (definitionally equal to) ``f p₁σ ... pₙσ`` is rewritten to ``vσ``,
  106. where ``σ`` is any substitution on the pattern variables ``x₁``,
  107. ... ``xₖ``.
  108. Since rewriting happens after normal reduction, rewrite rules are only
  109. applied to terms that would otherwise be neutral.
  110. .. _confluence-check:
  111. Confluence checking
  112. -------------------
  113. Agda can optionally check confluence of rewrite rules by enabling the
  114. ``--confluence-check`` flag. Concretely, it does so by enforcing two
  115. properties:
  116. 1. For any two left-hand sides of the rewrite rules that overlap
  117. (either at the root position or at a subterm), the most general
  118. unifier of the two left-hand sides is again a left-hand side of a
  119. rewrite rule. For example, if there are two rules ``suc m + n =
  120. suc (m + n)`` and ``m + suc n = suc (m + n)``, then there should
  121. also be a rule ``suc m + suc n = suc (suc (m + n))``.
  122. 2. Each rewrite rule should satisfy the *triangle property*: For any
  123. rewrite rule ``u = w`` and any single-step parallel unfolding ``u
  124. => v``, we should have another single-step parallel unfolding ``v
  125. => w``.
  126. There is also a flag ``--local-confluence-check`` that is less
  127. restrictive but only checks local confluence of rewrite rules. In case
  128. the rewrite rules are terminating (currently not checked), these two
  129. properties are equivalent.
  130. Advanced usage
  131. --------------
  132. Instead of importing ``Agda.Builtin.Equality.Rewrite``, a different
  133. type may be chosen as the rewrite relation by registering it as the
  134. ``REWRITE`` builtin. For example, using the pragma ``{-# BUILTIN
  135. REWRITE _~_ #-}`` registers the type ``_~_`` as the rewrite
  136. relation. To qualify as the rewrite relation, the type must take at
  137. least two arguments, and the final two arguments should be visible.