123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- ..
- ::
- {-# OPTIONS --rewriting --sized-types #-}
- module language.function-definitions where
- open import language.built-ins
- .. _function-definitions:
- ********************
- Function Definitions
- ********************
- Introduction
- ============
- A function is defined by first declaring its type followed by a number of
- equations called *clauses*. Each clause consists of the function being defined
- applied to a number of *patterns*, followed by ``=`` and a term called the
- *right-hand side*. For example:
- ::
- not : Bool → Bool
- not true = false
- not false = true
- Functions are allowed to call themselves recursively, for example:
- ::
- twice : Nat → Nat
- twice zero = zero
- twice (suc n) = suc (suc (twice n))
- General form
- ============
- The general form for defining a function is
- .. code-block:: agda
- f : (x₁ : A₁) → … → (xₙ : Aₙ) → B
- f p₁ … pₙ = d
- …
- f q₁ … qₙ = e
- where ``f`` is a new identifier, ``pᵢ`` and ``qᵢ`` are patterns of type ``Aᵢ``,
- and ``d`` and ``e`` are expressions.
- The declaration above gives the identifier ``f`` the type
- ``(x₁ : A₁) → … → (xₙ : Aₙ) → B`` and ``f`` is defined by the defining
- equations. Patterns are matched from top to bottom, i.e., the first pattern
- that matches the actual parameters is the one that is used.
- By default, Agda checks the following properties of a function definition:
- - The patterns in the left-hand side of each clause should consist only of
- constructors and variables.
- - No variable should occur more than once on the left-hand side of a single
- clause.
- - The patterns of all clauses should together cover all possible inputs of
- the function, see :ref:`coverage-checking`.
- - The function should be terminating on all possible inputs, see
- :ref:`termination-checking`.
- Special patterns
- ================
- In addition to constructors consisting of constructors and variables, Agda
- supports two special kinds of patterns: dot patterns and absurd patterns.
- .. _dot-patterns:
- Dot patterns
- ------------
- A dot pattern (also called *inaccessible pattern*) can be used when
- the only type-correct value of the argument is determined by the
- patterns given for the other arguments.
- The syntax for a dot pattern is ``.t``.
- As an example, consider the datatype ``Square`` defined as follows
- ::
- data Square : Nat → Set where
- sq : (m : Nat) → Square (m * m)
- Suppose we want to define a function ``root : (n : Nat) → Square n → Nat`` that
- takes as its arguments a number ``n`` and a proof that it is a square, and
- returns the square root of that number. We can do so as follows:
- ::
- root : (n : Nat) → Square n → Nat
- root .(m * m) (sq m) = m
- Notice that by matching on the argument of type ``Square n`` with the constructor
- ``sq : (m : Nat) → Square (m * m)``, ``n`` is forced to be equal to ``m * m``.
- In general, when matching on an argument of type ``D i₁ … iₙ`` with a constructor
- ``c : (x₁ : A₁) → … → (xₘ : Aₘ) → D j₁ … jₙ``, Agda will attempt to unify
- ``i₁ … iₙ`` with ``j₁ … jₙ``. When the unification algorithm instantiates a
- variable ``x`` with value ``t``, the corresponding argument of the function
- can be replaced by a dot pattern ``.t``. Using a dot pattern is optional, but
- can help readability. The following are also legal definitions of
- ``root``:
- Since Agda 2.4.2.4::
- root₁ : (n : Nat) → Square n → Nat
- root₁ _ (sq m) = m
- Since Agda 2.5.2::
- root₂ : (n : Nat) → Square n → Nat
- root₂ n (sq m) = m
- In the case of ``root₂``, ``n`` evaluates to ``m * m`` in the body of the
- function and is thus equivalent to
- ::
- root₃ : (n : Nat) → Square n → Nat
- root₃ _ (sq m) = let n = m * m in m
- .. _absurd-patterns:
- Absurd patterns
- ---------------
- Absurd patterns can be used when none of the constructors for a particular
- argument would be valid. The syntax for an absurd pattern is ``()``.
- As an example, if we have a datatype ``Even`` defined as follows
- ::
- data Even : Nat → Set where
- even-zero : Even zero
- even-plus2 : {n : Nat} → Even n → Even (suc (suc n))
- then we can define a function ``one-not-even : Even 1 → ⊥`` by using an absurd
- pattern:
- ::
- one-not-even : Even 1 → ⊥
- one-not-even ()
- Note that if the left-hand side of a clause contains an absurd pattern, its
- right-hand side must be omitted.
- In general, when matching on an argument of type ``D i₁ … iₙ`` with an absurd
- pattern, Agda will attempt for each constructor
- ``c : (x₁ : A₁) → … → (xₘ : Aₘ) → D j₁ … jₙ`` of the datatype ``D`` to unify
- ``i₁ … iₙ`` with ``j₁ … jₙ``. The absurd pattern will only be accepted if all
- of these unifications end in a conflict.
- As-patterns
- -----------
- As-patterns (or ``@-patterns``) can be used to name a pattern. The name has the
- same scope as normal pattern variables (i.e. the right-hand side, where clause,
- and dot patterns). The name reduces to the value of the named pattern. For example::
- module _ {A : Set} (_<_ : A → A → Bool) where
- merge : List A → List A → List A
- merge xs [] = xs
- merge [] ys = ys
- merge xs@(x ∷ xs₁) ys@(y ∷ ys₁) =
- if x < y then x ∷ merge xs₁ ys
- else y ∷ merge xs ys₁
- As-patterns are properly supported since Agda 2.5.2.
- .. _case-trees:
- Case trees
- ==========
- Internally, Agda represents function definitions as *case trees*. For example,
- a function definition
- ::
- max : Nat → Nat → Nat
- max zero n = n
- max m zero = m
- max (suc m) (suc n) = suc (max m n)
- will be represented internally as a case tree that looks like this:
- .. code-block:: agda
- max m n = case m of
- zero → n
- suc m' → case n of
- zero → suc m'
- suc n' → suc (max m' n')
- Note that because Agda uses this representation of the function
- ``max``, the clause ``max m zero = m`` does not hold definitionally
- (i.e. as a reduction rule). If you would try to prove that this
- equation holds, you would not be able to write ``refl``:
- .. code-block:: agda
- data _≡_ {A : Set} (x : A) : A → Set where
- refl : x ≡ x
- -- Does not work!
- lemma : (m : Nat) → max m zero ≡ m
- lemma = refl
- Clauses which do not hold definitionally are usually (but not always)
- the result of writing clauses by hand instead of using Agda's case
- split tactic. These clauses are :ref:`highlighted <highlight>` by
- Emacs.
- .. _catchall-pragma:
- The ``--exact-split`` flag causes Agda to raise an error whenever a
- clause in a definition by pattern matching cannot be made to hold
- definitionally. Specific clauses can be excluded from this check by
- means of the ``{-# CATCHALL #-}`` pragma.
- For instance, the above definition of ``max`` will be rejected when
- using the ``--exact-split`` flag because its second clause does not to
- hold definitionally.
- When using the :option:`--exact-split` flag, catch-all clauses have to
- be marked as such, for instance: ::
- eq : Nat → Nat → Bool
- eq zero zero = true
- eq (suc m) (suc n) = eq m n
- {-# CATCHALL #-}
- eq _ _ = false
- The :option:`--no-exact-split` flag can be used to override a global
- :option:`--exact-split` in a file, by adding a pragma
- ``{-# OPTIONS --no-exact-split #-}``. This option is enabled by
- default.
|