runtime-irrelevance.lagda.rst 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. ..
  2. ::
  3. {-# OPTIONS --cubical #-}
  4. module language.runtime-irrelevance where
  5. open import Agda.Primitive
  6. open import Agda.Builtin.Cubical.Path
  7. open import Agda.Builtin.Nat
  8. open import Agda.Builtin.List
  9. private
  10. variable
  11. a b : Level
  12. A B : Set a
  13. .. _runtime-irrelevance:
  14. ********************
  15. Run-time Irrelevance
  16. ********************
  17. From version 2.6.1 Agda supports run-time irrelevance (or erasure) annotations. Values marked as
  18. erased are not present at run time, and consequently the type checker enforces that no computations
  19. depend on erased values.
  20. Syntax
  21. ======
  22. A function or constructor argument is declared erased using the ``@0`` or ``@erased`` annotation.
  23. For example, the following definition of vectors guarantees that the length argument to ``_∷_`` is not
  24. present at runtime::
  25. data Vec (A : Set a) : @0 Nat → Set a where
  26. [] : Vec A 0
  27. _∷_ : ∀ {@0 n} → A → Vec A n → Vec A (suc n)
  28. The :ref:`GHC backend <ghc-backend>` compiles this to a datatype where the cons constructor takes only two
  29. arguments.
  30. .. note::
  31. In this particular case, the compiler identifies that the length argument can be erased also without the
  32. annotation, using Brady et al's forcing analysis :ref:`[1] <references>`. Marking it erased explictly, however,
  33. ensures that it is erased without relying on the analysis.
  34. .. note::
  35. In the type signature of a constructor or record field the
  36. parameters are always marked as erased, even if the parameters are
  37. not marked as erased in the data or record type's telescope.
  38. Erasure annotations can also appear in function arguments (both first-order and higher-order). For instance, here is
  39. an implementation of ``foldl`` on vectors::
  40. foldl : (B : @0 Nat → Set b)
  41. → (f : ∀ {@0 n} → B n → A → B (suc n))
  42. → (z : B 0)
  43. → ∀ {@0 n} → Vec A n → B n
  44. foldl B f z [] = z
  45. foldl B f z (x ∷ xs) = foldl (λ n → B (suc n)) (λ {n} → f {suc n}) (f z x) xs
  46. Here the length arguments to ``foldl`` and to ``f`` have been marked erased. As a result it gets compiled to the following
  47. Haskell code (modulo renaming):
  48. .. code-block:: text
  49. foldl f z xs
  50. = case xs of
  51. [] -> z
  52. x ∷ xs -> foldl f (f _ z x) xs
  53. In contrast to constructor arguments, erased arguments to higher-order functions are not removed completely, but
  54. instead replaced by a placeholder value ``_``. The crucial optimization enabled by the erasure annotation is compiling
  55. ``λ {n} → f {suc n}`` to simply ``f``, removing a terrible space leak from the program. Compare to the result of
  56. compiling without erasure:
  57. .. code-block:: text
  58. foldl f z xs
  59. = case xs of
  60. [] -> z
  61. x ∷ xs -> foldl (\ n -> f (1 + n)) (f 0 z x) xs
  62. It is also possible to mark top-level definitions as erased. This
  63. guarantees that they are only used in erased arguments and can be
  64. useful to ensure that code intended only for compile-time evaluation
  65. is not executed at run time. (One can also use erased things in the
  66. bodies of erased definitions.) For instance,
  67. ::
  68. @0 spec : Nat → Nat -- slow, but easy to verify
  69. impl : Nat → Nat -- fast, but hard to understand
  70. proof : ∀ n → spec n ≡ impl n
  71. ..
  72. ::
  73. spec n = n
  74. impl n = n
  75. proof n = λ _ → n
  76. Erased record fields become erased arguments to the record constructor and the projection functions
  77. are treated as erased definitions.
  78. Constructors can also be marked as erased. Here is one example:
  79. ::
  80. Is-proposition : Set a → Set a
  81. Is-proposition A = (x y : A) → x ≡ y
  82. data ∥_∥ (A : Set a) : Set a where
  83. ∣_∣ : A → ∥ A ∥
  84. @0 trivial : Is-proposition ∥ A ∥
  85. rec : @0 Is-proposition B → (A → B) → ∥ A ∥ → B
  86. rec p f ∣ x ∣ = f x
  87. rec p f (trivial x y i) = p (rec p f x) (rec p f y) i
  88. In the code above the constructor ``trivial`` is only available at
  89. compile-time, whereas ``∣_∣`` is also available at run-time. Clauses
  90. that match on erased constructors in non-erased positions are omitted
  91. by (at least some) compiler backends, so one can use erased names in
  92. the bodies of such clauses. (There is an
  93. :ref:`exception<erased-cubical>` for constructors that were not
  94. declared as erased, but that are treated as erased because they were
  95. defined using Cubical Agda, and are used in a module that uses the
  96. option :option:`--erased-cubical`.)
  97. .. _run-time-irrelevance-rules:
  98. Rules
  99. =====
  100. The typing rules are based on Conor McBride's "I Got Plenty o’Nuttin’" :ref:`[2] <references>` and
  101. Bob Atkey's "The Syntax and Semantics of Quantitative Type Theory" :ref:`[3] <references>`. In
  102. essence the type checker keeps track of whether it is running in *run-time mode*, checking something
  103. that is needed at run time, or *compile-time mode*, checking something that will be erased. In
  104. compile-time mode everything to do with erasure can safely be ignored, but in run-time mode the
  105. following restrictions apply:
  106. - Cannot use erased variables or definitions.
  107. - Cannot pattern match on erased arguments, unless there is at most
  108. one valid case (not counting erased constructors). If
  109. ``--without-K`` is enabled and there is one valid case, then the
  110. datatype must also not be indexed.
  111. Consider the function ``foo`` taking an erased vector argument:
  112. .. code-block:: agda
  113. foo : (n : Nat) (@0 xs : Vec Nat n) → Nat
  114. foo zero [] = 0
  115. foo (suc n) (x ∷ xs) = foo n xs
  116. This is okay (when the K rule is on), since after matching on the
  117. length, the matching on the vector does not provide any computational
  118. information, and any variables in the pattern (``x`` and ``xs`` in
  119. this case) are marked erased in turn. On the other hand, if we don't
  120. match on the length first, the type checker complains:
  121. .. code-block:: agda
  122. foo : (n : Nat) (@0 xs : Vec Nat n) → Nat
  123. foo n [] = 0
  124. foo n (x ∷ xs) = foo _ xs
  125. -- Error: Cannot branch on erased argument of datatype Vec Nat n
  126. The type checker enters compile-time mode when
  127. - checking erased arguments to a constructor or function,
  128. - checking the body of an erased definition,
  129. - checking the body of a clause that matches on an erased constructor,
  130. - checking the domain of an erased Π type, or
  131. - checking a type, i.e. when moving to the right of a ``:``, with some
  132. exceptions:
  133. - Compile-time mode is not entered for the domains of non-erased Π
  134. types.
  135. - If the K rule is off then compile-time mode is not entered for
  136. non-erased constructors (of fibrant type) or record fields.
  137. Note that the type checker does not enter compile-time mode based on
  138. the type a term is checked against (except that a distinction is
  139. sometimes made between fibrant and non-fibrant types). In particular,
  140. checking a term against ``Set`` does not trigger compile-time mode.
  141. .. _references:
  142. References
  143. ==========
  144. [1] Brady, Edwin, Conor McBride, and James McKinna. "Inductive Families Need Not Store Their Indices."
  145. International Workshop on Types for Proofs and Programs. Springer, Berlin, Heidelberg, 2003.
  146. [2] McBride, Conor. `"I Got Plenty o’Nuttin’." <https://personal.cis.strath.ac.uk/conor.mcbride/PlentyO-CR.pdf>`_
  147. A List of Successes That Can Change the World. Springer, Cham, 2016.
  148. [3] Atkey, Robert. `"The Syntax and Semantics of Quantitative Type Theory" <https://bentnib.org/quantitative-type-theory.html>`_.
  149. In LICS '18: Oxford, United Kingdom. 2018.