mutual-recursion.lagda.rst 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. ..
  2. ::
  3. module language.mutual-recursion where
  4. open import Agda.Builtin.Nat
  5. open import Agda.Builtin.Bool
  6. .. _mutual-recursion:
  7. ****************
  8. Mutual Recursion
  9. ****************
  10. Agda offers multiple ways to write mutually-defined data types, record types and functions.
  11. - :ref:`mutual-recursion-mutual-block`
  12. - :ref:`mutual-recursion-forward-declaration`
  13. - :ref:`mutual-recursion-interleaved-mutual`
  14. The last two are more expressive than the first one as they allow the interleaving of
  15. declarations and definitions thus making it possible for some types to refere to the
  16. constructors of a mutually-defined datatype.
  17. .. _mutual-recursion-interleaved-mutual:
  18. Interleaved mutual blocks
  19. -------------------------
  20. Mutual recursive functions can be written by placing them inside an ``interleaved mutual``
  21. block. The type signature of each function must come before its defining clauses and its
  22. usage sites on the right-hand side of other functions.
  23. The clauses for different functions can be interleaved e.g. for pedagogical purposes::
  24. interleaved mutual
  25. -- Declarations:
  26. even : Nat → Bool
  27. odd : Nat → Bool
  28. -- zero is even, not odd
  29. even zero = true
  30. odd zero = false
  31. -- suc case: switch evenness on the predecessor
  32. even (suc n) = odd n
  33. odd (suc n) = even n
  34. You can mix arbitrary declarations, such as modules and postulates, with mutually recursive
  35. definitions. For data types and records the following syntax is used to separate the
  36. declaration from the introduction of constructors in one or many ``data ... where`` blocks::
  37. interleaved mutual
  38. -- Declaration of a product record, a universe of codes, and a decoding function
  39. record _×_ (A B : Set) : Set
  40. data U : Set
  41. El : U → Set
  42. -- We have a code for the type of natural numbers in our universe
  43. data U where `Nat : U
  44. El `Nat = Nat
  45. -- Btw we know how to pair values in a record
  46. record _×_ A B where
  47. inductive; constructor _,_
  48. field fst : A; snd : B
  49. -- And we have a code for pairs in our universe
  50. data _ where
  51. _`×_ : (A B : U) → U
  52. El (A `× B) = El A × El B
  53. -- we can now build types of nested pairs of natural numbers
  54. ty-example : U
  55. ty-example = `Nat `× ((`Nat `× `Nat) `× `Nat)
  56. -- and their values
  57. val-example : El ty-example
  58. val-example = 0 , ((1 , 2) , 3)
  59. You can mix constructors for different data types in a ``data _ where`` block
  60. (underscore instead of name).
  61. The ``interleaved mutual`` blocks get desugared into the
  62. :ref:`mutual-recursion-forward-declaration` blocks described below by:
  63. - leaving the signatures where they are,
  64. - grouping the clauses for a function together with the first of them, and
  65. - grouping the constructors for a datatype together with the first of them.
  66. .. _mutual-recursion-forward-declaration:
  67. Forward declaration
  68. -------------------
  69. Mutual recursive functions can be written by placing the type signatures of all mutually
  70. recursive function before their definitions. The span of the mutual block will be
  71. automatically inferred by Agda:
  72. .. code-block:: agda
  73. f : A
  74. g : B[f]
  75. f = a[f, g]
  76. g = b[f, g].
  77. You can mix arbitrary declarations, such as modules and postulates, with mutually recursive definitions.
  78. For data types and records the following syntax is used to separate the declaration from the definition::
  79. -- Declaration.
  80. data Vec (A : Set) : Nat → Set -- Note the absence of ‘where’.
  81. -- Definition.
  82. data Vec A where -- Note the absence of a type signature.
  83. [] : Vec A zero
  84. _::_ : {n : Nat} → A → Vec A n → Vec A (suc n)
  85. -- Declaration.
  86. record Sigma (A : Set) (B : A → Set) : Set
  87. -- Definition.
  88. record Sigma A B where
  89. constructor _,_
  90. field fst : A
  91. snd : B fst
  92. The parameter lists in the second part of a data or record declaration behave like
  93. variables left-hand sides (although infix syntax is not supported). That is, they
  94. should have no type signatures, but implicit parameters can be omitted or bound by name.
  95. ..
  96. ::
  97. module Universe where
  98. Such a separation of declaration and definition is for instance needed when defining a set of codes for types and their interpretation as actual types (a so-called *universe*)::
  99. -- Declarations.
  100. data TypeCode : Set
  101. Interpretation : TypeCode → Set
  102. -- Definitions.
  103. data TypeCode where
  104. nat : TypeCode
  105. pi : (a : TypeCode) (b : Interpretation a → TypeCode) → TypeCode
  106. Interpretation nat = Nat
  107. Interpretation (pi a b) = (x : Interpretation a) → Interpretation (b x)
  108. .. note::
  109. In contrast to :ref:`mutual-recursion-interleaved-mutual`,
  110. in forward-declaration style we can only have one ``data ... where``
  111. block per data type.
  112. When making separated declarations/definitions private or abstract you should attach the ``private`` keyword to the declaration and the ``abstract`` keyword to the definition. For instance, a private, abstract function can be defined as
  113. ..
  114. ::
  115. module private-abstract (A : Set) (e : A) where
  116. ::
  117. private
  118. f : A
  119. abstract
  120. f = e
  121. .. _mutual-recursion-mutual-block:
  122. Old-style ``mutual`` blocks
  123. ----------------------------
  124. Mutual recursive functions can be written by placing the type signatures of all mutually
  125. recursive function before their definitions:
  126. .. code-block:: agda
  127. mutual
  128. f : A
  129. f = a[f, g]
  130. g : B[f]
  131. g = b[f, g]
  132. Using the ``mutual`` keyword,
  133. the *universe* example from above is expressed as follows::
  134. mutual
  135. data TypeCode : Set where
  136. nat : TypeCode
  137. pi : (a : TypeCode) (b : Interpretation a → TypeCode) → TypeCode
  138. Interpretation : TypeCode → Set
  139. Interpretation nat = Nat
  140. Interpretation (pi a b) = (x : Interpretation a) → Interpretation (b x)
  141. This alternative syntax desugars into the new syntax by sorting the
  142. content of the mutual block into a *declaration* and a *definition*
  143. part and placing the declarations before the definitions.
  144. *Declarations* comprise:
  145. - Type signatures of functions, ``data`` and ``record`` declarations, ``unquoteDecl``.
  146. (*Function* includes here ``postulate`` and ``primitive`` etc.)
  147. - Module statements, such as ``module`` aliases, ``import`` and ``open`` statements.
  148. - Pragmas that only need the name, but not the definition of the thing they affect (e.g. ``INJECTIVE``).
  149. *Definitions* comprise:
  150. - Function clauses, ``data`` constructors and ``record`` definitions, ``unquoteDef``.
  151. - ``pattern`` synonym definitions.
  152. - Pragmas that need the definition, e.g. ``INLINE``, ``ETA``, etc.
  153. - Pragmas that are not needed for type checking, like compiler pragmas.
  154. Module definitions with ``module ... where`` are not supported in old-style ``mutual`` blocks.