abstract-definitions.lagda.rst 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. ..
  2. ::
  3. {-# OPTIONS --rewriting --sized-types #-}
  4. module language.abstract-definitions where
  5. open import language.built-ins
  6. .. _abstract-definitions:
  7. ********************
  8. Abstract definitions
  9. ********************
  10. Definitions can be marked as abstract, for the purpose of hiding
  11. implementation details, or to speed up type-checking of other parts.
  12. In essence, abstract definitions behave like postulates, thus, do not
  13. reduce/compute. For instance, proofs whose content does not matter
  14. could be marked abstract, to prevent Agda from unfolding them (which
  15. might slow down type-checking).
  16. As a guiding principle, all the rules concerning ``abstract`` are
  17. designed to prevent the leaking of implementation details of abstract
  18. definitions. Similar concepts of other programming language include
  19. (non-representative sample):
  20. UCSD Pascal's and Java's interfaces and ML's signatures.
  21. (Especially when abstract definitions are used in combination with modules.)
  22. Synopsis
  23. --------
  24. * Declarations can be marked as abstract using the block keyword ``abstract``.
  25. * Outside of abstract blocks, abstract definitions do not reduce, they are treated as postulates,
  26. in particular:
  27. * Abstract functions never match, thus, do not reduce.
  28. * Abstract data types do not expose their constructors.
  29. * Abstract record types do not expose their fields nor constructor.
  30. * Other declarations cannot be abstract.
  31. * Inside abstract blocks, abstract definitions reduce while type checking definitions,
  32. but not while checking their type signatures.
  33. Otherwise, due to dependent types, one could leak implementation
  34. details (e.g. expose reduction behavior by using propositional
  35. equality).
  36. Consequently information from checking the body of a definition cannot leak
  37. into its type signature, effectively disabling type inference for abstract
  38. definitions. This means that all abstract definitions need a complete type
  39. signature.
  40. * The reach of the ``abstract`` keyword block extends recursively to
  41. the ``where``-blocks of a function and the declarations inside of a
  42. ``record`` declaration, but not inside modules declared in an
  43. abstract block.
  44. Examples
  45. --------
  46. Integers can be implemented in various ways, e.g. as difference of two
  47. natural numbers::
  48. module Integer where
  49. abstract
  50. ℤ : Set
  51. ℤ = Nat × Nat
  52. 0ℤ : ℤ
  53. 0ℤ = 0 , 0
  54. 1ℤ : ℤ
  55. 1ℤ = 1 , 0
  56. _+ℤ_ : (x y : ℤ) → ℤ
  57. (p , n) +ℤ (p' , n') = (p + p') , (n + n')
  58. -ℤ_ : ℤ → ℤ
  59. -ℤ (p , n) = (n , p)
  60. _≡ℤ_ : (x y : ℤ) → Set
  61. (p , n) ≡ℤ (p' , n') = (p + n') ≡ (p' + n)
  62. private
  63. postulate
  64. +comm : ∀ n m → (n + m) ≡ (m + n)
  65. invℤ : ∀ x → (x +ℤ (-ℤ x)) ≡ℤ 0ℤ
  66. invℤ (p , n) rewrite +comm (p + n) 0 | +comm p n = refl
  67. Using ``abstract`` we do not give away the actual representation of
  68. integers, nor the implementation of the operations. We can construct
  69. them from ``0ℤ``, ``1ℤ``, ``_+ℤ_``, and ``-ℤ``, but only reason about
  70. equality ``≡ℤ`` with the provided lemma ``invℤ``.
  71. The following property ``shape-of-0ℤ`` of the integer zero exposes the
  72. representation of integers as pairs. As such, it is rejected by Agda:
  73. when checking its type signature, ``proj₁ x`` fails to type check
  74. since ``x`` is of abstract type ``ℤ``. Remember that the abstract
  75. definition of ``ℤ`` does not unfold in type signatures, even when in
  76. an abstract block! To work around this we have to define aliases for
  77. the projections functions::
  78. -- A property about the representation of zero integers:
  79. abstract
  80. private
  81. posZ : ℤ → Nat
  82. posZ = proj₁
  83. negZ : ℤ → Nat
  84. negZ = proj₂
  85. shape-of-0ℤ : ∀ (x : ℤ) (is0ℤ : x ≡ℤ 0ℤ) → posZ x ≡ negZ x
  86. shape-of-0ℤ (p , n) refl rewrite +comm p 0 = refl
  87. By requiring ``shape-of-0ℤ`` to be private to type-check, leaking of
  88. representation details is prevented.
  89. Scope of abstraction
  90. --------------------
  91. In child modules,
  92. when checking an abstract definition,
  93. the abstract definitions of the parent module are transparent::
  94. module M1 where
  95. abstract
  96. x : Nat
  97. x = 0
  98. module M2 where
  99. abstract
  100. x-is-0 : x ≡ 0
  101. x-is-0 = refl
  102. Thus, child modules can see into the representation choices of their
  103. parent modules. However, parent modules cannot see like this into
  104. child modules, nor can sibling modules see through each others abstract
  105. definitions. An exception to this is anonymous modules, which share
  106. abstract scope with their parent module, allowing parent or sibling
  107. modules to see inside their abstract definitions.
  108. The reach of the ``abstract`` keyword does not extend into modules::
  109. module Parent where
  110. abstract
  111. module Child where
  112. y : Nat
  113. y = 0
  114. x : Nat
  115. x = 0 -- to avoid "useless abstract" error
  116. y-is-0 : Child.y ≡ 0
  117. y-is-0 = refl
  118. The declarations in module ``Child`` are not abstract!
  119. Abstract definitions with where-blocks
  120. --------------------------------------
  121. Definitions in a ``where`` block of an abstract definition are abstract
  122. as well. This means, they can see through the abstractions of their
  123. uncles::
  124. module Where where
  125. abstract
  126. x : Nat
  127. x = 0
  128. y : Nat
  129. y = x
  130. where
  131. x≡y : x ≡ 0
  132. x≡y = refl