termination-checking.lagda.rst 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. ..
  2. ::
  3. module language.termination-checking where
  4. open import Agda.Builtin.Bool
  5. open import Agda.Builtin.Nat
  6. .. _termination-checking:
  7. ********************
  8. Termination Checking
  9. ********************
  10. Not all recursive functions are permitted - Agda accepts only these recursive
  11. schemas that it can mechanically prove terminating.
  12. .. _termination-checking-primitive-recursion:
  13. Primitive recursion
  14. -------------------
  15. In the simplest case, a given argument must be exactly one constructor
  16. smaller in each recursive call. We call this scheme primitive
  17. recursion. A few correct examples:
  18. ::
  19. plus : Nat → Nat → Nat
  20. plus zero m = m
  21. plus (suc n) m = suc (plus n m)
  22. natEq : Nat → Nat → Bool
  23. natEq zero zero = true
  24. natEq zero (suc m) = false
  25. natEq (suc n) zero = false
  26. natEq (suc n) (suc m) = natEq n m
  27. Both ``plus`` and ``natEq`` are defined by primitive recursion.
  28. The recursive call in ``plus`` is OK because ``n`` is a subexpression
  29. of ``suc n`` (so ``n`` is structurally smaller than ``suc n``). So
  30. every time plus is recursively called the first argument is getting
  31. smaller and smaller. Since a natural number can only have a finite
  32. number of suc constructors we know that plus will always terminate.
  33. ``natEq`` terminates for the same reason, but in this case we can say
  34. that both the first and second arguments of natEq are decreasing.
  35. .. _termination-checking-structural-recursion:
  36. Structural recursion
  37. --------------------
  38. Agda's termination checker allows more definitions than just primitive
  39. recursive ones -- it allows structural recursion.
  40. This means that we require recursive calls to be on a (strict)
  41. subexpression of the argument (see ``fib`` below) - this is more
  42. general that just taking away one constructor at a time.
  43. ::
  44. fib : Nat → Nat
  45. fib zero = zero
  46. fib (suc zero) = suc zero
  47. fib (suc (suc n)) = plus (fib n) (fib (suc n))
  48. It also means that arguments may decrease in an lexicographic order -
  49. this can be thought of as nested primitive recursion (see ``ack``
  50. below).
  51. ::
  52. ack : Nat → Nat → Nat
  53. ack zero m = suc m
  54. ack (suc n) zero = ack n (suc zero)
  55. ack (suc n) (suc m) = ack n (ack (suc n) m)
  56. In ``ack`` either the first argument decreases or it stays the same and the second one decreases.
  57. This is the same as a lexicographic ordering.
  58. .. _termination-checking-with:
  59. With-functions
  60. --------------
  61. Pragmas and Options
  62. -------------------
  63. .. _non_terminating-pragma:
  64. * The ``NON_TERMINATING`` pragma
  65. This is a safer version of :ref:`TERMINATING <terminating-pragma>`
  66. which doesn't treat the affected functions as terminating. This
  67. means that ``NON_TERMINATING`` functions do not reduce during type
  68. checking. They do reduce at run-time and when invoking ``C-c C-n``
  69. at top-level (but not in a hole). The pragma was added in Agda
  70. 2.4.2.
  71. .. _terminating-pragma:
  72. * The ``TERMINATING`` pragma
  73. Switches off termination checker for individual function definitions
  74. and mutual blocks and marks them as terminating. Since Agda 2.4.2.1
  75. replaced the ``NO_TERMINATION_CHECK`` pragma.
  76. The pragma must precede a function definition or a mutual block. The
  77. pragma cannot be used in :option:`--safe` mode.
  78. Examples:
  79. ..
  80. ::
  81. module single where
  82. postulate A : Set
  83. * Skipping a single definition: before type signature::
  84. {-# TERMINATING #-}
  85. a : A
  86. a = a
  87. * Skipping a single definition: before first clause::
  88. b : A
  89. {-# TERMINATING #-}
  90. b = b
  91. * Skipping an old-style mutual block: Before `mutual` keyword::
  92. {-# TERMINATING #-}
  93. mutual
  94. c : A
  95. c = d
  96. d : A
  97. d = c
  98. * Skipping an old-style mutual block: Somewhere within `mutual`
  99. block before a type signature or first function clause::
  100. mutual
  101. {-# TERMINATING #-}
  102. e : A
  103. e = f
  104. f : A
  105. f = e
  106. * Skipping a new-style mutual block: Anywhere before a type
  107. signature or first function clause in the block::
  108. g : A
  109. h : A
  110. g = h
  111. {-# TERMINATING #-}
  112. h = g
  113. .. _termination-checking-references:
  114. References
  115. ----------
  116. `Andreas Abel, Foetus -- termination checker for simple functional programs
  117. <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.44.3494&rank=1>`_