From c7b529cd79d56ba30d98a459e9f08ccd9910e236 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 19:46:46 +0200 Subject: Extract Private inductive types from Gallina. --- .../language/gallina-specification-language.rst | 1428 -------------------- 1 file changed, 1428 deletions(-) diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst index 353bed1b3d..fc2481201f 100644 --- a/doc/sphinx/language/gallina-specification-language.rst +++ b/doc/sphinx/language/gallina-specification-language.rst @@ -1,940 +1,3 @@ -.. _gallinaspecificationlanguage: - ------------------------------------- - The Gallina specification language ------------------------------------- - -This chapter describes Gallina, the specification language of Coq. It allows -developing mathematical theories and to prove specifications of programs. The -theories are built from axioms, hypotheses, parameters, lemmas, theorems and -definitions of constants, functions, predicates and sets. - -.. _term: - -Terms -===== - -.. _gallina-identifiers: - -Qualified identifiers and simple identifiers --------------------------------------------- - -.. insertprodn qualid field_ident - -.. prodn:: - qualid ::= @ident {* @field_ident } - field_ident ::= .@ident - -*Qualified identifiers* (:n:`@qualid`) denote *global constants* -(definitions, lemmas, theorems, remarks or facts), *global variables* -(parameters or axioms), *inductive types* or *constructors of inductive -types*. *Simple identifiers* (or shortly :n:`@ident`) are a syntactic subset -of qualified identifiers. Identifiers may also denote *local variables*, -while qualified identifiers do not. - -Field identifiers, written :n:`@field_ident`, are identifiers prefixed by -`.` (dot) with no blank between the dot and the identifier. - - -Numerals and strings --------------------- - -.. insertprodn primitive_notations primitive_notations - -.. prodn:: - primitive_notations ::= @numeral - | @string - -Numerals and strings have no predefined semantics in the calculus. They are -merely notations that can be bound to objects through the notation mechanism -(see Chapter :ref:`syntax-extensions-and-notation-scopes` for details). -Initially, numerals are bound to Peano’s representation of natural -numbers (see :ref:`datatypes`). - -.. note:: - - Negative integers are not at the same level as :n:`@num`, for this - would make precedence unnatural. - -.. index:: - single: Set (sort) - single: SProp - single: Prop - single: Type - -Sorts ------ - -.. insertprodn sort univ_constraint - -.. prodn:: - sort ::= Set - | Prop - | SProp - | Type - | Type @%{ _ %} - | Type @%{ @universe %} - universe ::= max ( {+, @universe_expr } ) - | @universe_expr - universe_expr ::= @universe_name {? + @num } - universe_name ::= @qualid - | Set - | Prop - univ_annot ::= @%{ {* @universe_level } %} - universe_level ::= Set - | Prop - | Type - | _ - | @qualid - univ_decl ::= @%{ {* @ident } {? + } {? %| {*, @univ_constraint } {? + } } %} - univ_constraint ::= @universe_name {| < | = | <= } @universe_name - -There are four sorts :g:`SProp`, :g:`Prop`, :g:`Set` and :g:`Type`. - -- :g:`SProp` is the universe of *definitionally irrelevant - propositions* (also called *strict propositions*). - -- :g:`Prop` is the universe of *logical propositions*. The logical propositions - themselves are typing the proofs. We denote propositions by :n:`@form`. - This constitutes a semantic subclass of the syntactic class :n:`@term`. - -- :g:`Set` is the universe of *program types* or *specifications*. The - specifications themselves are typing the programs. We denote - specifications by :n:`@specif`. This constitutes a semantic subclass of - the syntactic class :n:`@term`. - -- :g:`Type` is the type of sorts. - -More on sorts can be found in Section :ref:`sorts`. - -.. _binders: - -Binders -------- - -.. insertprodn open_binders binder - -.. prodn:: - open_binders ::= {+ @name } : @term - | {+ @binder } - name ::= _ - | @ident - binder ::= @name - | ( {+ @name } : @type ) - | ( @name {? : @type } := @term ) - | @implicit_binders - | @generalizing_binder - | ( @name : @type %| @term ) - | ' @pattern0 - -Various constructions such as :g:`fun`, :g:`forall`, :g:`fix` and :g:`cofix` -*bind* variables. A binding is represented by an identifier. If the binding -variable is not used in the expression, the identifier can be replaced by the -symbol :g:`_`. When the type of a bound variable cannot be synthesized by the -system, it can be specified with the notation :n:`(@ident : @type)`. There is also -a notation for a sequence of binding variables sharing the same type: -:n:`({+ @ident} : @type)`. A -binder can also be any pattern prefixed by a quote, e.g. :g:`'(x,y)`. - -Some constructions allow the binding of a variable to value. This is -called a “let-binder”. The entry :n:`@binder` of the grammar accepts -either an assumption binder as defined above or a let-binder. The notation in -the latter case is :n:`(@ident := @term)`. In a let-binder, only one -variable can be introduced at the same time. It is also possible to give -the type of the variable as follows: -:n:`(@ident : @type := @term)`. - -Lists of :n:`@binder`\s are allowed. In the case of :g:`fun` and :g:`forall`, -it is intended that at least one binder of the list is an assumption otherwise -fun and forall gets identical. Moreover, parentheses can be omitted in -the case of a single sequence of bindings sharing the same type (e.g.: -:g:`fun (x y z : A) => t` can be shortened in :g:`fun x y z : A => t`). - -.. index:: fun ... => ... - -Abstractions: fun ------------------ - -The expression :n:`fun @ident : @type => @term` defines the -*abstraction* of the variable :n:`@ident`, of type :n:`@type`, over the term -:n:`@term`. It denotes a function of the variable :n:`@ident` that evaluates to -the expression :n:`@term` (e.g. :g:`fun x : A => x` denotes the identity -function on type :g:`A`). The keyword :g:`fun` can be followed by several -binders as given in Section :ref:`binders`. Functions over -several variables are equivalent to an iteration of one-variable -functions. For instance the expression -:n:`fun {+ @ident__i } : @type => @term` -denotes the same function as :n:`{+ fun @ident__i : @type => } @term`. If -a let-binder occurs in -the list of binders, it is expanded to a let-in definition (see -Section :ref:`let-in`). - -.. index:: forall - -Products: forall ----------------- - -.. insertprodn term_forall_or_fun term_forall_or_fun - -.. prodn:: - term_forall_or_fun ::= forall @open_binders , @term - | fun @open_binders => @term - -The expression :n:`forall @ident : @type, @term` denotes the -*product* of the variable :n:`@ident` of type :n:`@type`, over the term :n:`@term`. -As for abstractions, :g:`forall` is followed by a binder list, and products -over several variables are equivalent to an iteration of one-variable -products. Note that :n:`@term` is intended to be a type. - -If the variable :n:`@ident` occurs in :n:`@term`, the product is called -*dependent product*. The intention behind a dependent product -:g:`forall x : A, B` is twofold. It denotes either -the universal quantification of the variable :g:`x` of type :g:`A` -in the proposition :g:`B` or the functional dependent product from -:g:`A` to :g:`B` (a construction usually written -:math:`\Pi_{x:A}.B` in set theory). - -Non dependent product types have a special notation: :g:`A -> B` stands for -:g:`forall _ : A, B`. The *non dependent product* is used both to denote -the propositional implication and function types. - -Applications ------------- - -.. insertprodn term_application arg - -.. prodn:: - term_application ::= @term1 {+ @arg } - | @ @qualid_annotated {+ @term1 } - arg ::= ( @ident := @term ) - | @term1 - -:n:`@term__fun @term` denotes applying the function :n:`@term__fun` to :token:`term`. - -:n:`@term__fun {+ @term__i }` denotes applying -:n:`@term__fun` to the arguments :n:`@term__i`. It is -equivalent to :n:`( … ( @term__fun @term__1 ) … ) @term__n`: -associativity is to the left. - -The notation :n:`(@ident := @term)` for arguments is used for making -explicit the value of implicit arguments (see -Section :ref:`explicit-applications`). - -.. index:: - single: ... : ... (type cast) - single: ... <: ... - single: ... <<: ... - -Type cast ---------- - -.. insertprodn term_cast term_cast - -.. prodn:: - term_cast ::= @term10 <: @term - | @term10 <<: @term - | @term10 : @term - | @term10 :> - -The expression :n:`@term : @type` is a type cast expression. It enforces -the type of :n:`@term` to be :n:`@type`. - -:n:`@term <: @type` locally sets up the virtual machine for checking that -:n:`@term` has type :n:`@type`. - -:n:`@term <<: @type` uses native compilation for checking that :n:`@term` -has type :n:`@type`. - -.. index:: _ - -Inferable subterms ------------------- - -Expressions often contain redundant pieces of information. Subterms that can be -automatically inferred by Coq can be replaced by the symbol ``_`` and Coq will -guess the missing piece of information. - -.. index:: let ... := ... (term) - -.. _let-in: - -Let-in definitions ------------------- - -.. insertprodn term_let term_let - -.. prodn:: - term_let ::= let @name {? : @type } := @term in @term - | let @name {+ @binder } {? : @type } := @term in @term - | let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term - | let ' @pattern := @term {? return @term100 } in @term - | let ' @pattern in @pattern := @term return @term100 in @term - -:n:`let @ident := @term in @term’` -denotes the local binding of :n:`@term` to the variable -:n:`@ident` in :n:`@term`’. There is a syntactic sugar for let-in -definition of functions: :n:`let @ident {+ @binder} := @term in @term’` -stands for :n:`let @ident := fun {+ @binder} => @term in @term’`. - -.. index:: match ... with ... - -Definition by cases: match --------------------------- - -.. insertprodn term_match pattern0 - -.. prodn:: - term_match ::= match {+, @case_item } {? return @term100 } with {? %| } {*| @eqn } end - case_item ::= @term100 {? as @name } {? in @pattern } - eqn ::= {+| {+, @pattern } } => @term - pattern ::= @pattern10 : @term - | @pattern10 - pattern10 ::= @pattern1 as @name - | @pattern1 {* @pattern1 } - | @ @qualid {* @pattern1 } - pattern1 ::= @pattern0 % @scope_key - | @pattern0 - pattern0 ::= @qualid - | %{%| {* @qualid := @pattern } %|%} - | _ - | ( {+| @pattern } ) - | @numeral - | @string - -Objects of inductive types can be destructured by a case-analysis -construction called *pattern matching* expression. A pattern matching -expression is used to analyze the structure of an inductive object and -to apply specific treatments accordingly. - -This paragraph describes the basic form of pattern matching. See -Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description -of the general form. The basic form of pattern matching is characterized -by a single :n:`@case_item` expression, an :n:`@eqn` restricted to a -single :n:`@pattern` and :n:`@pattern` restricted to the form -:n:`@qualid {* @ident}`. - -The expression -:n:`match @term {? return @term100 } with {+| @pattern__i => @term__i } end` denotes a -*pattern matching* over the term :n:`@term` (expected to be -of an inductive type :math:`I`). The :n:`@term__i` -are the *branches* of the pattern matching -expression. Each :n:`@pattern__i` has the form :n:`@qualid @ident` -where :n:`@qualid` must denote a constructor. There should be -exactly one branch for every constructor of :math:`I`. - -The :n:`return @term100` clause gives the type returned by the whole match -expression. There are several cases. In the *non dependent* case, all -branches have the same type, and the :n:`return @term100` specifies that type. -In this case, :n:`return @term100` can usually be omitted as it can be -inferred from the type of the branches [1]_. - -In the *dependent* case, there are three subcases. In the first subcase, -the type in each branch may depend on the exact value being matched in -the branch. In this case, the whole pattern matching itself depends on -the term being matched. This dependency of the term being matched in the -return type is expressed with an :n:`@ident` clause where :n:`@ident` -is dependent in the return type. For instance, in the following example: - -.. coqtop:: in - - Inductive bool : Type := true : bool | false : bool. - Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. - Inductive or (A:Prop) (B:Prop) : Prop := - | or_introl : A -> or A B - | or_intror : B -> or A B. - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b as x return or (eq bool x true) (eq bool x false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`" -and ":g:`or (eq bool false true) (eq bool false false)`" while the whole -pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`", -the identifier :g:`b` being used to represent the dependency. - -.. note:: - - When the term being matched is a variable, the ``as`` clause can be - omitted and the term being matched can serve itself as binding name in - the return type. For instance, the following alternative definition is - accepted and has the same meaning as the previous one. - - .. coqtop:: none - - Reset bool_case. - - .. coqtop:: in - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b return or (eq bool b true) (eq bool b false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -The second subcase is only relevant for annotated inductive types such -as the equality predicate (see Section :ref:`coq-equality`), -the order predicate on natural numbers or the type of lists of a given -length (see Section :ref:`matching-dependent`). In this configuration, the -type of each branch can depend on the type dependencies specific to the -branch and the whole pattern matching expression has a type determined -by the specific dependencies in the type of the term being matched. This -dependency of the return type in the annotations of the inductive type -is expressed with a clause in the form -:n:`in @qualid {+ _ } {+ @pattern }`, where - -- :n:`@qualid` is the inductive type of the term being matched; - -- the holes :n:`_` match the parameters of the inductive type: the - return type is not dependent on them. - -- each :n:`@pattern` matches the annotations of the - inductive type: the return type is dependent on them - -- in the basic case which we describe below, each :n:`@pattern` - is a name :n:`@ident`; see :ref:`match-in-patterns` for the - general case - -For instance, in the following example: - -.. coqtop:: in - - Definition eq_sym (A:Type) (x y:A) (H:eq A x y) : eq A y x := - match H in eq _ _ z return eq A z x with - | eq_refl _ _ => eq_refl A x - end. - -the type of the branch is :g:`eq A x x` because the third argument of -:g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the -type of the whole pattern matching expression has type :g:`eq A y x` because the -third argument of eq is y in the type of H. This dependency of the case analysis -in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the -return type. - -Finally, the third subcase is a combination of the first and second -subcase. In particular, it only applies to pattern matching on terms in -a type with annotations. For this third subcase, both the clauses ``as`` and -``in`` are available. - -There are specific notations for case analysis on types with one or two -constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see -Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). - -.. index:: - single: fix - single: cofix - -Recursive and co-recursive functions: fix and cofix ---------------------------------------------------- - -.. insertprodn term_fix fixannot - -.. prodn:: - term_fix ::= let fix @fix_body in @term - | fix @fix_body {? {+ with @fix_body } for @ident } - fix_body ::= @ident {* @binder } {? @fixannot } {? : @type } := @term - fixannot ::= %{ struct @ident %} - | %{ wf @one_term @ident %} - | %{ measure @one_term {? @ident } {? @one_term } %} - - -The expression ":n:`fix @ident__1 @binder__1 : @type__1 := @term__1 with … with @ident__n @binder__n : @type__n := @term__n for @ident__i`" denotes the -:math:`i`-th component of a block of functions defined by mutual structural -recursion. It is the local counterpart of the :cmd:`Fixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -The association of a single fixpoint and a local definition have a special -syntax: :n:`let fix @ident {* @binder } := @term in` stands for -:n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for co-fixpoints. - -Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` -only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in -commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. - -.. insertprodn term_cofix cofix_body - -.. prodn:: - term_cofix ::= let cofix @cofix_body in @term - | cofix @cofix_body {? {+ with @cofix_body } for @ident } - cofix_body ::= @ident {* @binder } {? : @type } := @term - -The expression -":n:`cofix @ident__1 @binder__1 : @type__1 with … with @ident__n @binder__n : @type__n for @ident__i`" -denotes the :math:`i`-th component of a block of terms defined by a mutual guarded -co-recursion. It is the local counterpart of the :cmd:`CoFixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -.. _vernacular: - -The Vernacular -============== - -.. _gallina-assumptions: - -Assumptions ------------ - -Assumptions extend the environment with axioms, parameters, hypotheses -or variables. An assumption binds an :n:`@ident` to a :n:`@type`. It is accepted -by Coq if and only if this :n:`@type` is a correct type in the environment -preexisting the declaration and if :n:`@ident` was not previously defined in -the same module. This :n:`@type` is considered to be the type (or -specification, or statement) assumed by :n:`@ident` and we say that :n:`@ident` -has type :n:`@type`. - -.. _Axiom: - -.. cmd:: @assumption_token {? Inline {? ( @num ) } } {| {+ ( @assumpt ) } | @assumpt } - :name: Axiom; Axioms; Conjecture; Conjectures; Hypothesis; Hypotheses; Parameter; Parameters; Variable; Variables - - .. insertprodn assumption_token of_type - - .. prodn:: - assumption_token ::= {| Axiom | Axioms } - | {| Conjecture | Conjectures } - | {| Parameter | Parameters } - | {| Hypothesis | Hypotheses } - | {| Variable | Variables } - assumpt ::= {+ @ident_decl } @of_type - ident_decl ::= @ident {? @univ_decl } - of_type ::= {| : | :> | :>> } @type - - These commands bind one or more :n:`@ident`\(s) to specified :n:`@type`\(s) as their specifications in - the global context. The fact asserted by the :n:`@type` (or, equivalently, the existence - of an object of this type) is accepted as a postulate. - - :cmd:`Axiom`, :cmd:`Conjecture`, :cmd:`Parameter` and their plural forms - are equivalent. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident`\s accessible by :cmd:`Import` and its variants - only through their fully qualified names. - - Similarly, :cmd:`Hypothesis`, :cmd:`Variable` and their plural forms are equivalent. Outside - of a section, these are equivalent to :n:`Local Parameter`. Inside a section, the - :n:`@ident`\s defined are only accessible within the section. When the current section - is closed, the :n:`@ident`\(s) become undefined and every object depending on them will be explicitly - parameterized (i.e., the variables are *discharged*). See Section :ref:`section-mechanism`. - - The :n:`Inline` clause is only relevant inside functors. See :cmd:`Module`. - -.. example:: Simple assumptions - - .. coqtop:: reset in - - Parameter X Y : Set. - Parameter (R : X -> Y -> Prop) (S : Y -> X -> Prop). - Axiom R_S_inv : forall x y, R x y <-> S y x. - -.. exn:: @ident already exists. - :name: @ident already exists. (Axiom) - :undocumented: - -.. warn:: @ident is declared as a local axiom - - Warning generated when using :cmd:`Variable` or its equivalent - instead of :n:`Local Parameter` or its equivalent. - -.. note:: - We advise using the commands :cmd:`Axiom`, :cmd:`Conjecture` and - :cmd:`Hypothesis` (and their plural forms) for logical postulates (i.e. when - the assertion :n:`@type` is of sort :g:`Prop`), and to use the commands - :cmd:`Parameter` and :cmd:`Variable` (and their plural forms) in other cases - (corresponding to the declaration of an abstract object of the given type). - -.. _gallina-definitions: - -Definitions ------------ - -Definitions extend the environment with associations of names to terms. -A definition can be seen as a way to give a meaning to a name or as a -way to abbreviate a term. In any case, the name can later be replaced at -any time by its definition. - -The operation of unfolding a name into its definition is called -:math:`\delta`-conversion (see Section :ref:`delta-reduction`). A -definition is accepted by the system if and only if the defined term is -well-typed in the current context of the definition and if the name is -not already used. The name defined by the definition is called a -*constant* and the term it refers to is its *body*. A definition has a -type which is the type of its body. - -A formal presentation of constants and environments is given in -Section :ref:`typing-rules`. - -.. cmd:: {| Definition | Example } @ident_decl @def_body - :name: Definition; Example - - .. insertprodn def_body def_body - - .. prodn:: - def_body ::= {* @binder } {? : @type } := {? @reduce } @term - | {* @binder } : @type - - These commands bind :n:`@term` to the name :n:`@ident` in the environment, - provided that :n:`@term` is well-typed. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident` accessible by :cmd:`Import` and its variants - only through their fully qualified names. - If :n:`@reduce` is present then :n:`@ident` is bound to the result of the specified - computation on :n:`@term`. - - These commands also support the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`program` and - :attr:`canonical` attributes. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - The form :n:`Definition @ident : @type := @term` checks that the type of :n:`@term` - is definitionally equal to :n:`@type`, and registers :n:`@ident` as being of type - :n:`@type`, and bound to value :n:`@term`. - - The form :n:`Definition @ident {* @binder } : @type := @term` is equivalent to - :n:`Definition @ident : forall {* @binder }, @type := fun {* @binder } => @term`. - - .. seealso:: :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`. - - .. exn:: @ident already exists. - :name: @ident already exists. (Definition) - :undocumented: - - .. exn:: The term @term has type @type while it is expected to have type @type'. - :undocumented: - -.. _gallina-inductive-definitions: - -Inductive types ---------------- - -.. cmd:: Inductive @inductive_definition {* with @inductive_definition } - - .. insertprodn inductive_definition constructor - - .. prodn:: - inductive_definition ::= {? > } @ident_decl {* @binder } {? %| {* @binder } } {? : @type } {? := {? @constructors_or_record } } {? @decl_notations } - constructors_or_record ::= {? %| } {+| @constructor } - | {? @ident } %{ {*; @record_field } %} - constructor ::= @ident {* @binder } {? @of_type } - - This command defines one or more - inductive types and its constructors. Coq generates destructors - depending on the universe that the inductive type belongs to. - - The destructors are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, - :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``, which - respectively correspond to elimination principles on :g:`Type`, :g:`Prop`, - :g:`Set` and :g:`SProp`. The type of the destructors - expresses structural induction/recursion principles over objects of - type :n:`@ident`. The constant :n:`@ident`\ ``_ind`` is always - generated, whereas :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_rect`` - may be impossible to derive (for example, when :n:`@ident` is a - proposition). - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - Mutually inductive types can be defined by including multiple :n:`@inductive_definition`\s. - The :n:`@ident`\s are simultaneously added to the environment before the types of constructors are checked. - Each :n:`@ident` can be used independently thereafter. - See :ref:`mutually_inductive_types`. - - If the entire inductive definition is parameterized with :n:`@binder`\s, the parameters correspond - to a local context in which the entire set of inductive declarations is interpreted. - For this reason, the parameters must be strictly the same for each inductive type. - See :ref:`parametrized-inductive-types`. - - Constructor :n:`@ident`\s can come with :n:`@binder`\s, in which case - the actual type of the constructor is :n:`forall {* @binder }, @type`. - - .. exn:: Non strictly positive occurrence of @ident in @type. - - The types of the constructors have to satisfy a *positivity condition* - (see Section :ref:`positivity`). This condition ensures the soundness of - the inductive definition. The positivity checking can be disabled using - the :flag:`Positivity Checking` flag (see :ref:`controlling-typing-flags`). - - .. exn:: The conclusion of @type is not valid; it must be built from @ident. - - The conclusion of the type of the constructors must be the inductive type - :n:`@ident` being defined (or :n:`@ident` applied to arguments in - the case of annotated inductive types — cf. next section). - -The following subsections show examples of simple inductive types, -simple annotated inductive types, simple parametric inductive types, -mutually inductive types and private (matching) inductive types. - -.. _simple-inductive-types: - -Simple inductive types -~~~~~~~~~~~~~~~~~~~~~~ - -A simple inductive type belongs to a universe that is a simple :n:`@sort`. - -.. example:: - - The set of natural numbers is defined as: - - .. coqtop:: reset all - - Inductive nat : Set := - | O : nat - | S : nat -> nat. - - The type nat is defined as the least :g:`Set` containing :g:`O` and closed by - the :g:`S` constructor. The names :g:`nat`, :g:`O` and :g:`S` are added to the - environment. - - This definition generates four elimination principles: - :g:`nat_rect`, :g:`nat_ind`, :g:`nat_rec` and :g:`nat_sind`. The type of :g:`nat_ind` is: - - .. coqtop:: all - - Check nat_ind. - - This is the well known structural induction principle over natural - numbers, i.e. the second-order form of Peano’s induction principle. It - allows proving universal properties of natural numbers (:g:`forall - n:nat, P n`) by induction on :g:`n`. - - The types of :g:`nat_rect`, :g:`nat_rec` and :g:`nat_sind` are similar, except that they - apply to, respectively, :g:`(P:nat->Type)`, :g:`(P:nat->Set)` and :g:`(P:nat->SProp)`. They correspond to - primitive induction principles (allowing dependent types) respectively - over sorts ```Type``, ``Set`` and ``SProp``. - -In the case where inductive types don't have annotations (the next section -gives an example of annotations), a constructor can be defined -by giving the type of its arguments alone. - -.. example:: - - .. coqtop:: reset none - - Reset nat. - - .. coqtop:: in - - Inductive nat : Set := O | S (_:nat). - -Simple annotated inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In annotated inductive types, the universe where the inductive type -is defined is no longer a simple :n:`@sort`, but what is called an arity, -which is a type whose conclusion is a :n:`@sort`. - -.. example:: - - As an example of annotated inductive types, let us define the - :g:`even` predicate: - - .. coqtop:: all - - Inductive even : nat -> Prop := - | even_0 : even O - | even_SS : forall n:nat, even n -> even (S (S n)). - - The type :g:`nat->Prop` means that :g:`even` is a unary predicate (inductively - defined) over natural numbers. The type of its two constructors are the - defining clauses of the predicate :g:`even`. The type of :g:`even_ind` is: - - .. coqtop:: all - - Check even_ind. - - From a mathematical point of view, this asserts that the natural numbers satisfying - the predicate :g:`even` are exactly in the smallest set of naturals satisfying the - clauses :g:`even_0` or :g:`even_SS`. This is why, when we want to prove any - predicate :g:`P` over elements of :g:`even`, it is enough to prove it for :g:`O` - and to prove that if any natural number :g:`n` satisfies :g:`P` its double - successor :g:`(S (S n))` satisfies also :g:`P`. This is analogous to the - structural induction principle we got for :g:`nat`. - -.. _parametrized-inductive-types: - -Parameterized inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the previous example, each constructor introduces a different -instance of the predicate :g:`even`. In some cases, all the constructors -introduce the same generic instance of the inductive definition, in -which case, instead of an annotation, we use a context of parameters -which are :n:`@binder`\s shared by all the constructors of the definition. - -Parameters differ from inductive type annotations in that the -conclusion of each type of constructor invokes the inductive type with -the same parameter values of its specification. - -.. example:: - - A typical example is the definition of polymorphic lists: - - .. coqtop:: all - - Inductive list (A:Set) : Set := - | nil : list A - | cons : A -> list A -> list A. - - In the type of :g:`nil` and :g:`cons`, we write ":g:`list A`" and not - just ":g:`list`". The constructors :g:`nil` and :g:`cons` have these types: - - .. coqtop:: all - - Check nil. - Check cons. - - Observe that the destructors are also quantified with :g:`(A:Set)`, for example: - - .. coqtop:: all - - Check list_ind. - - Once again, the types of the constructor arguments and of the conclusion can be omitted: - - .. coqtop:: none - - Reset list. - - .. coqtop:: in - - Inductive list (A:Set) : Set := nil | cons (_:A) (_:list A). - -.. note:: - + The constructor type can - recursively invoke the inductive definition on an argument which is not - the parameter itself. - - One can define : - - .. coqtop:: all - - Inductive list2 (A:Set) : Set := - | nil2 : list2 A - | cons2 : A -> list2 (A*A) -> list2 A. - - that can also be written by specifying only the type of the arguments: - - .. coqtop:: all reset - - Inductive list2 (A:Set) : Set := - | nil2 - | cons2 (_:A) (_:list2 (A*A)). - - But the following definition will give an error: - - .. coqtop:: all - - Fail Inductive listw (A:Set) : Set := - | nilw : listw (A*A) - | consw : A -> listw (A*A) -> listw (A*A). - - because the conclusion of the type of constructors should be :g:`listw A` - in both cases. - - + A parameterized inductive definition can be defined using annotations - instead of parameters but it will sometimes give a different (bigger) - sort for the inductive definition and will produce a less convenient - rule for case elimination. - -.. flag:: Uniform Inductive Parameters - - When this flag is set (it is off by default), - inductive definitions are abstracted over their parameters - before type checking constructors, allowing to write: - - .. coqtop:: all - - Set Uniform Inductive Parameters. - Inductive list3 (A:Set) : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - - This behavior is essentially equivalent to starting a new section - and using :cmd:`Context` to give the uniform parameters, like so - (cf. :ref:`section-mechanism`): - - .. coqtop:: all reset - - Section list3. - Context (A:Set). - Inductive list3 : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - End list3. - - For finer control, you can use a ``|`` between the uniform and - the non-uniform parameters: - - .. coqtop:: in reset - - Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop - := Acc_in : (forall y, R y x -> Acc y) -> Acc x. - - The flag can then be seen as deciding whether the ``|`` is at the - beginning (when the flag is unset) or at the end (when it is set) - of the parameters when not explicitly given. - -.. seealso:: - Section :ref:`inductive-definitions` and the :tacn:`induction` tactic. - -.. _mutually_inductive_types: - -Mutually defined inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. example:: Mutually defined inductive types - - A typical example of mutually inductive data types is trees and - forests. We assume two types :g:`A` and :g:`B` that are given as variables. The types can - be declared like this: - - .. coqtop:: in - - Parameters A B : Set. - - Inductive tree : Set := node : A -> forest -> tree - - with forest : Set := - | leaf : B -> forest - | cons : tree -> forest -> forest. - - This declaration automatically generates eight induction principles. They are not the most - general principles, but they correspond to each inductive part seen as a single inductive definition. - - To illustrate this point on our example, here are the types of :g:`tree_rec` - and :g:`forest_rec`. - - .. coqtop:: all - - Check tree_rec. - - Check forest_rec. - - Assume we want to parameterize our mutual inductive definitions with the - two type variables :g:`A` and :g:`B`, the declaration should be - done as follows: - - .. coqdoc:: - - Inductive tree (A B:Set) : Set := node : A -> forest A B -> tree A B - - with forest (A B:Set) : Set := - | leaf : B -> forest A B - | cons : tree A B -> forest A B -> forest A B. - - Assume we define an inductive definition inside a section - (cf. :ref:`section-mechanism`). When the section is closed, the variables - declared in the section and occurring free in the declaration are added as - parameters to the inductive definition. - -.. seealso:: - A generic command :cmd:`Scheme` is useful to build automatically various - mutual induction principles. - Private (matching) inductive types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -959,494 +22,3 @@ Private (matching) inductive types End Foo. Import Foo. Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - -Variants -~~~~~~~~ - -.. cmd:: Variant @variant_definition {* with @variant_definition } - - .. insertprodn variant_definition variant_definition - - .. prodn:: - variant_definition ::= @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? %| } {+| @constructor } {? @decl_notations } - - The :cmd:`Variant` command is similar to the :cmd:`Inductive` command, except - that it disallows recursive definition of types (for instance, lists cannot - be defined using :cmd:`Variant`). No induction scheme is generated for - this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - .. exn:: The @num th argument of @ident must be @ident in @type. - :undocumented: - -.. _coinductive-types: - -Co-inductive types ------------------- - -The objects of an inductive type are well-founded with respect to the -constructors of the type. In other words, such objects contain only a -*finite* number of constructors. Co-inductive types arise from relaxing -this condition, and admitting types whose objects contain an infinity of -constructors. Infinite objects are introduced by a non-ending (but -effective) process of construction, defined in terms of the constructors -of the type. - -.. cmd:: CoInductive @inductive_definition {* with @inductive_definition } - - This command introduces a co-inductive type. - The syntax of the command is the same as the command :cmd:`Inductive`. - No principle of induction is derived from the definition of a co-inductive - type, since such principles only make sense for inductive types. - For co-inductive types, the only elimination principle is case analysis. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - -.. example:: - - The type of infinite sequences of natural numbers, usually called streams, - is an example of a co-inductive type. - - .. coqtop:: in - - CoInductive Stream : Set := Seq : nat -> Stream -> Stream. - - The usual destructors on streams :g:`hd:Stream->nat` and :g:`tl:Str->Str` - can be defined as follows: - - .. coqtop:: in - - Definition hd (x:Stream) := let (a,s) := x in a. - Definition tl (x:Stream) := let (a,s) := x in s. - -Definitions of co-inductive predicates and blocks of mutually -co-inductive definitions are also allowed. - -.. example:: - - The extensional equality on streams is an example of a co-inductive type: - - .. coqtop:: in - - CoInductive EqSt : Stream -> Stream -> Prop := - eqst : forall s1 s2:Stream, - hd s1 = hd s2 -> EqSt (tl s1) (tl s2) -> EqSt s1 s2. - - In order to prove the extensional equality of two streams :g:`s1` and :g:`s2` - we have to construct an infinite proof of equality, that is, an infinite - object of type :g:`(EqSt s1 s2)`. We will see how to introduce infinite - objects in Section :ref:`cofixpoint`. - -Caveat -~~~~~~ - -The ability to define co-inductive types by constructors, hereafter called -*positive co-inductive types*, is known to break subject reduction. The story is -a bit long: this is due to dependent pattern-matching which implies -propositional η-equality, which itself would require full η-conversion for -subject reduction to hold, but full η-conversion is not acceptable as it would -make type checking undecidable. - -Since the introduction of primitive records in Coq 8.5, an alternative -presentation is available, called *negative co-inductive types*. This consists -in defining a co-inductive type as a primitive record type through its -projections. Such a technique is akin to the *co-pattern* style that can be -found in e.g. Agda, and preserves subject reduction. - -The above example can be rewritten in the following way. - -.. coqtop:: none - - Reset Stream. - -.. coqtop:: all - - Set Primitive Projections. - CoInductive Stream : Set := Seq { hd : nat; tl : Stream }. - CoInductive EqSt (s1 s2: Stream) : Prop := eqst { - eqst_hd : hd s1 = hd s2; - eqst_tl : EqSt (tl s1) (tl s2); - }. - -Some properties that hold over positive streams are lost when going to the -negative presentation, typically when they imply equality over streams. -For instance, propositional η-equality is lost when going to the negative -presentation. It is nonetheless logically consistent to recover it through an -axiom. - -.. coqtop:: all - - Axiom Stream_eta : forall s: Stream, s = Seq (hd s) (tl s). - -More generally, as in the case of positive coinductive types, it is consistent -to further identify extensional equality of coinductive types with propositional -equality: - -.. coqtop:: all - - Axiom Stream_ext : forall (s1 s2: Stream), EqSt s1 s2 -> s1 = s2. - -As of Coq 8.9, it is now advised to use negative co-inductive types rather than -their positive counterparts. - -.. seealso:: - :ref:`primitive_projections` for more information about negative - records and primitive projections. - - -Definition of recursive functions ---------------------------------- - -Definition of functions by recursion over inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This section describes the primitive form of definition by recursion over -inductive objects. See the :cmd:`Function` command for more advanced -constructions. - -.. _Fixpoint: - -.. cmd:: Fixpoint @fix_definition {* with @fix_definition } - - .. insertprodn fix_definition fix_definition - - .. prodn:: - fix_definition ::= @ident_decl {* @binder } {? @fixannot } {? : @type } {? := @term } {? @decl_notations } - - This command allows defining functions by pattern matching over inductive - objects using a fixed point construction. The meaning of this declaration is - to define :n:`@ident` as a recursive function with arguments specified by - the :n:`@binder`\s such that :n:`@ident` applied to arguments - corresponding to these :n:`@binder`\s has type :n:`@type`, and is - equivalent to the expression :n:`@term`. The type of :n:`@ident` is - consequently :n:`forall {* @binder }, @type` and its value is equivalent - to :n:`fun {* @binder } => @term`. - - To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical - constraints on a special argument called the decreasing argument. They - are needed to ensure that the :cmd:`Fixpoint` definition always terminates. - The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to - let the user tell the system which argument decreases along the recursive calls. - - The :n:`{struct @ident}` annotation may be left implicit, in which case the - system successively tries arguments from left to right until it finds one - that satisfies the decreasing condition. - - :cmd:`Fixpoint` without the :attr:`program` attribute does not support the - :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. - - The :n:`with` clause allows simultaneously defining several mutual fixpoints. - It is especially useful when defining functions over mutually defined - inductive types. Example: :ref:`Mutual Fixpoints`. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - .. note:: - - + Some fixpoints may have several arguments that fit as decreasing - arguments, and this choice influences the reduction of the fixpoint. - Hence an explicit annotation must be used if the leftmost decreasing - argument is not the desired one. Writing explicit annotations can also - speed up type checking of large mutual fixpoints. - - + In order to keep the strong normalization property, the fixed point - reduction will only be performed when the argument in position of the - decreasing argument (which type should be in an inductive definition) - starts with a constructor. - - - .. example:: - - One can define the addition function as : - - .. coqtop:: all - - Fixpoint add (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (add p m) - end. - - The match operator matches a value (here :g:`n`) with the various - constructors of its (inductive) type. The remaining arguments give the - respective values to be returned, as functions of the parameters of the - corresponding constructor. Thus here when :g:`n` equals :g:`O` we return - :g:`m`, and when :g:`n` equals :g:`(S p)` we return :g:`(S (add p m))`. - - The match operator is formally described in - Section :ref:`match-construction`. - The system recognizes that in the inductive call :g:`(add p m)` the first - argument actually decreases because it is a *pattern variable* coming - from :g:`match n with`. - - .. example:: - - The following definition is not correct and generates an error message: - - .. coqtop:: all - - Fail Fixpoint wrongplus (n m:nat) {struct n} : nat := - match m with - | O => n - | S p => S (wrongplus n p) - end. - - because the declared decreasing argument :g:`n` does not actually - decrease in the recursive call. The function computing the addition over - the second argument should rather be written: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct m} : nat := - match m with - | O => n - | S p => S (plus n p) - end. - - .. example:: - - The recursive call may not only be on direct subterms of the recursive - variable :g:`n` but also on a deeper subterm and we can directly write - the function :g:`mod2` which gives the remainder modulo 2 of a natural - number. - - .. coqtop:: all - - Fixpoint mod2 (n:nat) : nat := - match n with - | O => O - | S p => match p with - | O => S O - | S q => mod2 q - end - end. - -.. _example_mutual_fixpoints: - - .. example:: Mutual fixpoints - - The size of trees and forests can be defined the following way: - - .. coqtop:: all - - Fixpoint tree_size (t:tree) : nat := - match t with - | node a f => S (forest_size f) - end - with forest_size (f:forest) : nat := - match f with - | leaf b => 1 - | cons t f' => (tree_size t + forest_size f') - end. - -.. _cofixpoint: - -Definitions of recursive objects in co-inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. cmd:: CoFixpoint @cofix_definition {* with @cofix_definition } - - .. insertprodn cofix_definition cofix_definition - - .. prodn:: - cofix_definition ::= @ident_decl {* @binder } {? : @type } {? := @term } {? @decl_notations } - - This command introduces a method for constructing an infinite object of a - coinductive type. For example, the stream containing all natural numbers can - be introduced applying the following method to the number :g:`O` (see - Section :ref:`coinductive-types` for the definition of :g:`Stream`, :g:`hd` - and :g:`tl`): - - .. coqtop:: all - - CoFixpoint from (n:nat) : Stream := Seq n (from (S n)). - - Unlike recursive definitions, there is no decreasing argument in a - co-recursive definition. To be admissible, a method of construction must - provide at least one extra constructor of the infinite object for each - iteration. A syntactical guard condition is imposed on co-recursive - definitions in order to ensure this: each recursive call in the - definition must be protected by at least one constructor, and only by - constructors. That is the case in the former definition, where the single - recursive call of :g:`from` is guarded by an application of :g:`Seq`. - On the contrary, the following recursive function does not satisfy the - guard condition: - - .. coqtop:: all - - Fail CoFixpoint filter (p:nat -> bool) (s:Stream) : Stream := - if p (hd s) then Seq (hd s) (filter p (tl s)) else filter p (tl s). - - The elimination of co-recursive definition is done lazily, i.e. the - definition is expanded only when it occurs at the head of an application - which is the argument of a case analysis expression. In any other - context, it is considered as a canonical expression which is completely - evaluated. We can test this using the command :cmd:`Eval`, which computes - the normal forms of a term: - - .. coqtop:: all - - Eval compute in (from 0). - Eval compute in (hd (from 0)). - Eval compute in (tl (from 0)). - - As in the :cmd:`Fixpoint` command, the :n:`with` clause allows simultaneously - defining several mutual cofixpoints. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - -.. _Computations: - -Computations ------------- - -.. insertprodn reduce pattern_occ - -.. prodn:: - reduce ::= Eval @red_expr in - red_expr ::= red - | hnf - | simpl {? @delta_flag } {? @ref_or_pattern_occ } - | cbv {? @strategy_flag } - | cbn {? @strategy_flag } - | lazy {? @strategy_flag } - | compute {? @delta_flag } - | vm_compute {? @ref_or_pattern_occ } - | native_compute {? @ref_or_pattern_occ } - | unfold {+, @unfold_occ } - | fold {+ @one_term } - | pattern {+, @pattern_occ } - | @ident - delta_flag ::= {? - } [ {+ @smart_qualid } ] - strategy_flag ::= {+ @red_flags } - | @delta_flag - red_flags ::= beta - | iota - | match - | fix - | cofix - | zeta - | delta {? @delta_flag } - ref_or_pattern_occ ::= @smart_qualid {? at @occs_nums } - | @one_term {? at @occs_nums } - occs_nums ::= {+ {| @num | @ident } } - | - {| @num | @ident } {* @int_or_var } - int_or_var ::= @int - | @ident - unfold_occ ::= @smart_qualid {? at @occs_nums } - pattern_occ ::= @one_term {? at @occs_nums } - -See :ref:`Conversion-rules`. - -.. todo:: Add text here - -.. _Assertions: - -Assertions and proofs ---------------------- - -An assertion states a proposition (or a type) of which the proof (or an -inhabitant of the type) is interactively built using tactics. The interactive -proof mode is described in Chapter :ref:`proofhandling` and the tactics in -Chapter :ref:`Tactics`. The basic assertion command is: - -.. cmd:: @thm_token @ident_decl {* @binder } : @type {* with @ident_decl {* @binder } : @type } - :name: Theorem; Lemma; Fact; Remark; Corollary; Proposition; Property - - .. insertprodn thm_token thm_token - - .. prodn:: - thm_token ::= Theorem - | Lemma - | Fact - | Remark - | Corollary - | Proposition - | Property - - After the statement is asserted, Coq needs a proof. Once a proof of - :n:`@type` under the assumptions represented by :n:`@binder`\s is given and - validated, the proof is generalized into a proof of :n:`forall {* @binder }, @type` and - the theorem is bound to the name :n:`@ident` in the environment. - - Forms using the :n:`with` clause are useful for theorems that are proved by simultaneous induction - over a mutually inductive assumption, or that assert mutually dependent - statements in some mutual co-inductive type. It is equivalent to - :cmd:`Fixpoint` or :cmd:`CoFixpoint` but using tactics to build the proof of - the statements (or the body of the specification, depending on the point of - view). The inductive or co-inductive types on which the induction or - coinduction has to be done is assumed to be non ambiguous and is guessed by - the system. - - Like in a :cmd:`Fixpoint` or :cmd:`CoFixpoint` definition, the induction hypotheses - have to be used on *structurally smaller* arguments (for a :cmd:`Fixpoint`) or - be *guarded by a constructor* (for a :cmd:`CoFixpoint`). The verification that - recursive proof arguments are correct is done only at the time of registering - the lemma in the environment. To know if the use of induction hypotheses is - correct at some time of the interactive development of a proof, use the - command :cmd:`Guarded`. - - .. exn:: The term @term has type @type which should be Set, Prop or Type. - :undocumented: - - .. exn:: @ident already exists. - :name: @ident already exists. (Theorem) - - The name you provided is already defined. You have then to choose - another name. - - .. exn:: Nested proofs are not allowed unless you turn the Nested Proofs Allowed flag on. - - You are asserting a new statement while already being in proof editing mode. - This feature, called nested proofs, is disabled by default. - To activate it, turn the :flag:`Nested Proofs Allowed` flag on. - -Proofs start with the keyword :cmd:`Proof`. Then Coq enters the proof editing mode -until the proof is completed. In proof editing mode, the user primarily enters -tactics, which are described in chapter :ref:`Tactics`. The user may also enter -commands to manage the proof editing mode. They are described in Chapter -:ref:`proofhandling`. - -When the proof is complete, use the :cmd:`Qed` command so the kernel verifies -the proof and adds it to the environment. - -.. note:: - - #. Several statements can be simultaneously asserted provided the - :flag:`Nested Proofs Allowed` flag was turned on. - - #. Not only other assertions but any vernacular command can be given - while in the process of proving a given assertion. In this case, the - command is understood as if it would have been given before the - statements still to be proved. Nonetheless, this practice is discouraged - and may stop working in future versions. - - #. Proofs ended by :cmd:`Qed` are declared opaque. Their content cannot be - unfolded (see :ref:`performingcomputations`), thus - realizing some form of *proof-irrelevance*. To be able to unfold a - proof, the proof should be ended by :cmd:`Defined`. - - #. :cmd:`Proof` is recommended but can currently be omitted. On the opposite - side, :cmd:`Qed` (or :cmd:`Defined`) is mandatory to validate a proof. - - #. One can also use :cmd:`Admitted` in place of :cmd:`Qed` to turn the - current asserted statement into an axiom and exit the proof editing mode. - -.. [1] - Except if the inductive type is empty in which case there is no - equation that can be used to infer the return type. -- cgit v1.2.3 From b0e3404de4dff81680861517f70c496af1d92bbc Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 19:48:08 +0200 Subject: Create a new file on Variants. --- doc/sphinx/language/core/variants.rst | 24 ++++++++++++++++++++++ .../language/gallina-specification-language.rst | 24 ---------------------- 2 files changed, 24 insertions(+), 24 deletions(-) create mode 100644 doc/sphinx/language/core/variants.rst delete mode 100644 doc/sphinx/language/gallina-specification-language.rst diff --git a/doc/sphinx/language/core/variants.rst b/doc/sphinx/language/core/variants.rst new file mode 100644 index 0000000000..fc2481201f --- /dev/null +++ b/doc/sphinx/language/core/variants.rst @@ -0,0 +1,24 @@ +Private (matching) inductive types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. attr:: private(matching) + + This attribute can be used to forbid the use of the :g:`match` + construct on objects of this inductive type outside of the module + where it is defined. There is also a legacy syntax using the + ``Private`` prefix (cf. :n:`@legacy_attr`). + + The main use case of private (matching) inductive types is to emulate + quotient types / higher-order inductive types in projects such as + the `HoTT library `_. + +.. example:: + + .. coqtop:: all + + Module Foo. + #[ private(matching) ] Inductive my_nat := my_O : my_nat | my_S : my_nat -> my_nat. + Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). + End Foo. + Import Foo. + Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst deleted file mode 100644 index fc2481201f..0000000000 --- a/doc/sphinx/language/gallina-specification-language.rst +++ /dev/null @@ -1,24 +0,0 @@ -Private (matching) inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attr:: private(matching) - - This attribute can be used to forbid the use of the :g:`match` - construct on objects of this inductive type outside of the module - where it is defined. There is also a legacy syntax using the - ``Private`` prefix (cf. :n:`@legacy_attr`). - - The main use case of private (matching) inductive types is to emulate - quotient types / higher-order inductive types in projects such as - the `HoTT library `_. - -.. example:: - - .. coqtop:: all - - Module Foo. - #[ private(matching) ] Inductive my_nat := my_O : my_nat | my_S : my_nat -> my_nat. - Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - End Foo. - Import Foo. - Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). -- cgit v1.2.3 From abe9dbda38c046f700b83373e18e9593df5d3d41 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 19:49:16 +0200 Subject: Extract Variants from Gallina. --- .../language/gallina-specification-language.rst | 1429 -------------------- 1 file changed, 1429 deletions(-) diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst index 353bed1b3d..ff4212bdd4 100644 --- a/doc/sphinx/language/gallina-specification-language.rst +++ b/doc/sphinx/language/gallina-specification-language.rst @@ -1,965 +1,3 @@ -.. _gallinaspecificationlanguage: - ------------------------------------- - The Gallina specification language ------------------------------------- - -This chapter describes Gallina, the specification language of Coq. It allows -developing mathematical theories and to prove specifications of programs. The -theories are built from axioms, hypotheses, parameters, lemmas, theorems and -definitions of constants, functions, predicates and sets. - -.. _term: - -Terms -===== - -.. _gallina-identifiers: - -Qualified identifiers and simple identifiers --------------------------------------------- - -.. insertprodn qualid field_ident - -.. prodn:: - qualid ::= @ident {* @field_ident } - field_ident ::= .@ident - -*Qualified identifiers* (:n:`@qualid`) denote *global constants* -(definitions, lemmas, theorems, remarks or facts), *global variables* -(parameters or axioms), *inductive types* or *constructors of inductive -types*. *Simple identifiers* (or shortly :n:`@ident`) are a syntactic subset -of qualified identifiers. Identifiers may also denote *local variables*, -while qualified identifiers do not. - -Field identifiers, written :n:`@field_ident`, are identifiers prefixed by -`.` (dot) with no blank between the dot and the identifier. - - -Numerals and strings --------------------- - -.. insertprodn primitive_notations primitive_notations - -.. prodn:: - primitive_notations ::= @numeral - | @string - -Numerals and strings have no predefined semantics in the calculus. They are -merely notations that can be bound to objects through the notation mechanism -(see Chapter :ref:`syntax-extensions-and-notation-scopes` for details). -Initially, numerals are bound to Peano’s representation of natural -numbers (see :ref:`datatypes`). - -.. note:: - - Negative integers are not at the same level as :n:`@num`, for this - would make precedence unnatural. - -.. index:: - single: Set (sort) - single: SProp - single: Prop - single: Type - -Sorts ------ - -.. insertprodn sort univ_constraint - -.. prodn:: - sort ::= Set - | Prop - | SProp - | Type - | Type @%{ _ %} - | Type @%{ @universe %} - universe ::= max ( {+, @universe_expr } ) - | @universe_expr - universe_expr ::= @universe_name {? + @num } - universe_name ::= @qualid - | Set - | Prop - univ_annot ::= @%{ {* @universe_level } %} - universe_level ::= Set - | Prop - | Type - | _ - | @qualid - univ_decl ::= @%{ {* @ident } {? + } {? %| {*, @univ_constraint } {? + } } %} - univ_constraint ::= @universe_name {| < | = | <= } @universe_name - -There are four sorts :g:`SProp`, :g:`Prop`, :g:`Set` and :g:`Type`. - -- :g:`SProp` is the universe of *definitionally irrelevant - propositions* (also called *strict propositions*). - -- :g:`Prop` is the universe of *logical propositions*. The logical propositions - themselves are typing the proofs. We denote propositions by :n:`@form`. - This constitutes a semantic subclass of the syntactic class :n:`@term`. - -- :g:`Set` is the universe of *program types* or *specifications*. The - specifications themselves are typing the programs. We denote - specifications by :n:`@specif`. This constitutes a semantic subclass of - the syntactic class :n:`@term`. - -- :g:`Type` is the type of sorts. - -More on sorts can be found in Section :ref:`sorts`. - -.. _binders: - -Binders -------- - -.. insertprodn open_binders binder - -.. prodn:: - open_binders ::= {+ @name } : @term - | {+ @binder } - name ::= _ - | @ident - binder ::= @name - | ( {+ @name } : @type ) - | ( @name {? : @type } := @term ) - | @implicit_binders - | @generalizing_binder - | ( @name : @type %| @term ) - | ' @pattern0 - -Various constructions such as :g:`fun`, :g:`forall`, :g:`fix` and :g:`cofix` -*bind* variables. A binding is represented by an identifier. If the binding -variable is not used in the expression, the identifier can be replaced by the -symbol :g:`_`. When the type of a bound variable cannot be synthesized by the -system, it can be specified with the notation :n:`(@ident : @type)`. There is also -a notation for a sequence of binding variables sharing the same type: -:n:`({+ @ident} : @type)`. A -binder can also be any pattern prefixed by a quote, e.g. :g:`'(x,y)`. - -Some constructions allow the binding of a variable to value. This is -called a “let-binder”. The entry :n:`@binder` of the grammar accepts -either an assumption binder as defined above or a let-binder. The notation in -the latter case is :n:`(@ident := @term)`. In a let-binder, only one -variable can be introduced at the same time. It is also possible to give -the type of the variable as follows: -:n:`(@ident : @type := @term)`. - -Lists of :n:`@binder`\s are allowed. In the case of :g:`fun` and :g:`forall`, -it is intended that at least one binder of the list is an assumption otherwise -fun and forall gets identical. Moreover, parentheses can be omitted in -the case of a single sequence of bindings sharing the same type (e.g.: -:g:`fun (x y z : A) => t` can be shortened in :g:`fun x y z : A => t`). - -.. index:: fun ... => ... - -Abstractions: fun ------------------ - -The expression :n:`fun @ident : @type => @term` defines the -*abstraction* of the variable :n:`@ident`, of type :n:`@type`, over the term -:n:`@term`. It denotes a function of the variable :n:`@ident` that evaluates to -the expression :n:`@term` (e.g. :g:`fun x : A => x` denotes the identity -function on type :g:`A`). The keyword :g:`fun` can be followed by several -binders as given in Section :ref:`binders`. Functions over -several variables are equivalent to an iteration of one-variable -functions. For instance the expression -:n:`fun {+ @ident__i } : @type => @term` -denotes the same function as :n:`{+ fun @ident__i : @type => } @term`. If -a let-binder occurs in -the list of binders, it is expanded to a let-in definition (see -Section :ref:`let-in`). - -.. index:: forall - -Products: forall ----------------- - -.. insertprodn term_forall_or_fun term_forall_or_fun - -.. prodn:: - term_forall_or_fun ::= forall @open_binders , @term - | fun @open_binders => @term - -The expression :n:`forall @ident : @type, @term` denotes the -*product* of the variable :n:`@ident` of type :n:`@type`, over the term :n:`@term`. -As for abstractions, :g:`forall` is followed by a binder list, and products -over several variables are equivalent to an iteration of one-variable -products. Note that :n:`@term` is intended to be a type. - -If the variable :n:`@ident` occurs in :n:`@term`, the product is called -*dependent product*. The intention behind a dependent product -:g:`forall x : A, B` is twofold. It denotes either -the universal quantification of the variable :g:`x` of type :g:`A` -in the proposition :g:`B` or the functional dependent product from -:g:`A` to :g:`B` (a construction usually written -:math:`\Pi_{x:A}.B` in set theory). - -Non dependent product types have a special notation: :g:`A -> B` stands for -:g:`forall _ : A, B`. The *non dependent product* is used both to denote -the propositional implication and function types. - -Applications ------------- - -.. insertprodn term_application arg - -.. prodn:: - term_application ::= @term1 {+ @arg } - | @ @qualid_annotated {+ @term1 } - arg ::= ( @ident := @term ) - | @term1 - -:n:`@term__fun @term` denotes applying the function :n:`@term__fun` to :token:`term`. - -:n:`@term__fun {+ @term__i }` denotes applying -:n:`@term__fun` to the arguments :n:`@term__i`. It is -equivalent to :n:`( … ( @term__fun @term__1 ) … ) @term__n`: -associativity is to the left. - -The notation :n:`(@ident := @term)` for arguments is used for making -explicit the value of implicit arguments (see -Section :ref:`explicit-applications`). - -.. index:: - single: ... : ... (type cast) - single: ... <: ... - single: ... <<: ... - -Type cast ---------- - -.. insertprodn term_cast term_cast - -.. prodn:: - term_cast ::= @term10 <: @term - | @term10 <<: @term - | @term10 : @term - | @term10 :> - -The expression :n:`@term : @type` is a type cast expression. It enforces -the type of :n:`@term` to be :n:`@type`. - -:n:`@term <: @type` locally sets up the virtual machine for checking that -:n:`@term` has type :n:`@type`. - -:n:`@term <<: @type` uses native compilation for checking that :n:`@term` -has type :n:`@type`. - -.. index:: _ - -Inferable subterms ------------------- - -Expressions often contain redundant pieces of information. Subterms that can be -automatically inferred by Coq can be replaced by the symbol ``_`` and Coq will -guess the missing piece of information. - -.. index:: let ... := ... (term) - -.. _let-in: - -Let-in definitions ------------------- - -.. insertprodn term_let term_let - -.. prodn:: - term_let ::= let @name {? : @type } := @term in @term - | let @name {+ @binder } {? : @type } := @term in @term - | let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term - | let ' @pattern := @term {? return @term100 } in @term - | let ' @pattern in @pattern := @term return @term100 in @term - -:n:`let @ident := @term in @term’` -denotes the local binding of :n:`@term` to the variable -:n:`@ident` in :n:`@term`’. There is a syntactic sugar for let-in -definition of functions: :n:`let @ident {+ @binder} := @term in @term’` -stands for :n:`let @ident := fun {+ @binder} => @term in @term’`. - -.. index:: match ... with ... - -Definition by cases: match --------------------------- - -.. insertprodn term_match pattern0 - -.. prodn:: - term_match ::= match {+, @case_item } {? return @term100 } with {? %| } {*| @eqn } end - case_item ::= @term100 {? as @name } {? in @pattern } - eqn ::= {+| {+, @pattern } } => @term - pattern ::= @pattern10 : @term - | @pattern10 - pattern10 ::= @pattern1 as @name - | @pattern1 {* @pattern1 } - | @ @qualid {* @pattern1 } - pattern1 ::= @pattern0 % @scope_key - | @pattern0 - pattern0 ::= @qualid - | %{%| {* @qualid := @pattern } %|%} - | _ - | ( {+| @pattern } ) - | @numeral - | @string - -Objects of inductive types can be destructured by a case-analysis -construction called *pattern matching* expression. A pattern matching -expression is used to analyze the structure of an inductive object and -to apply specific treatments accordingly. - -This paragraph describes the basic form of pattern matching. See -Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description -of the general form. The basic form of pattern matching is characterized -by a single :n:`@case_item` expression, an :n:`@eqn` restricted to a -single :n:`@pattern` and :n:`@pattern` restricted to the form -:n:`@qualid {* @ident}`. - -The expression -:n:`match @term {? return @term100 } with {+| @pattern__i => @term__i } end` denotes a -*pattern matching* over the term :n:`@term` (expected to be -of an inductive type :math:`I`). The :n:`@term__i` -are the *branches* of the pattern matching -expression. Each :n:`@pattern__i` has the form :n:`@qualid @ident` -where :n:`@qualid` must denote a constructor. There should be -exactly one branch for every constructor of :math:`I`. - -The :n:`return @term100` clause gives the type returned by the whole match -expression. There are several cases. In the *non dependent* case, all -branches have the same type, and the :n:`return @term100` specifies that type. -In this case, :n:`return @term100` can usually be omitted as it can be -inferred from the type of the branches [1]_. - -In the *dependent* case, there are three subcases. In the first subcase, -the type in each branch may depend on the exact value being matched in -the branch. In this case, the whole pattern matching itself depends on -the term being matched. This dependency of the term being matched in the -return type is expressed with an :n:`@ident` clause where :n:`@ident` -is dependent in the return type. For instance, in the following example: - -.. coqtop:: in - - Inductive bool : Type := true : bool | false : bool. - Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. - Inductive or (A:Prop) (B:Prop) : Prop := - | or_introl : A -> or A B - | or_intror : B -> or A B. - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b as x return or (eq bool x true) (eq bool x false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`" -and ":g:`or (eq bool false true) (eq bool false false)`" while the whole -pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`", -the identifier :g:`b` being used to represent the dependency. - -.. note:: - - When the term being matched is a variable, the ``as`` clause can be - omitted and the term being matched can serve itself as binding name in - the return type. For instance, the following alternative definition is - accepted and has the same meaning as the previous one. - - .. coqtop:: none - - Reset bool_case. - - .. coqtop:: in - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b return or (eq bool b true) (eq bool b false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -The second subcase is only relevant for annotated inductive types such -as the equality predicate (see Section :ref:`coq-equality`), -the order predicate on natural numbers or the type of lists of a given -length (see Section :ref:`matching-dependent`). In this configuration, the -type of each branch can depend on the type dependencies specific to the -branch and the whole pattern matching expression has a type determined -by the specific dependencies in the type of the term being matched. This -dependency of the return type in the annotations of the inductive type -is expressed with a clause in the form -:n:`in @qualid {+ _ } {+ @pattern }`, where - -- :n:`@qualid` is the inductive type of the term being matched; - -- the holes :n:`_` match the parameters of the inductive type: the - return type is not dependent on them. - -- each :n:`@pattern` matches the annotations of the - inductive type: the return type is dependent on them - -- in the basic case which we describe below, each :n:`@pattern` - is a name :n:`@ident`; see :ref:`match-in-patterns` for the - general case - -For instance, in the following example: - -.. coqtop:: in - - Definition eq_sym (A:Type) (x y:A) (H:eq A x y) : eq A y x := - match H in eq _ _ z return eq A z x with - | eq_refl _ _ => eq_refl A x - end. - -the type of the branch is :g:`eq A x x` because the third argument of -:g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the -type of the whole pattern matching expression has type :g:`eq A y x` because the -third argument of eq is y in the type of H. This dependency of the case analysis -in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the -return type. - -Finally, the third subcase is a combination of the first and second -subcase. In particular, it only applies to pattern matching on terms in -a type with annotations. For this third subcase, both the clauses ``as`` and -``in`` are available. - -There are specific notations for case analysis on types with one or two -constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see -Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). - -.. index:: - single: fix - single: cofix - -Recursive and co-recursive functions: fix and cofix ---------------------------------------------------- - -.. insertprodn term_fix fixannot - -.. prodn:: - term_fix ::= let fix @fix_body in @term - | fix @fix_body {? {+ with @fix_body } for @ident } - fix_body ::= @ident {* @binder } {? @fixannot } {? : @type } := @term - fixannot ::= %{ struct @ident %} - | %{ wf @one_term @ident %} - | %{ measure @one_term {? @ident } {? @one_term } %} - - -The expression ":n:`fix @ident__1 @binder__1 : @type__1 := @term__1 with … with @ident__n @binder__n : @type__n := @term__n for @ident__i`" denotes the -:math:`i`-th component of a block of functions defined by mutual structural -recursion. It is the local counterpart of the :cmd:`Fixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -The association of a single fixpoint and a local definition have a special -syntax: :n:`let fix @ident {* @binder } := @term in` stands for -:n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for co-fixpoints. - -Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` -only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in -commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. - -.. insertprodn term_cofix cofix_body - -.. prodn:: - term_cofix ::= let cofix @cofix_body in @term - | cofix @cofix_body {? {+ with @cofix_body } for @ident } - cofix_body ::= @ident {* @binder } {? : @type } := @term - -The expression -":n:`cofix @ident__1 @binder__1 : @type__1 with … with @ident__n @binder__n : @type__n for @ident__i`" -denotes the :math:`i`-th component of a block of terms defined by a mutual guarded -co-recursion. It is the local counterpart of the :cmd:`CoFixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -.. _vernacular: - -The Vernacular -============== - -.. _gallina-assumptions: - -Assumptions ------------ - -Assumptions extend the environment with axioms, parameters, hypotheses -or variables. An assumption binds an :n:`@ident` to a :n:`@type`. It is accepted -by Coq if and only if this :n:`@type` is a correct type in the environment -preexisting the declaration and if :n:`@ident` was not previously defined in -the same module. This :n:`@type` is considered to be the type (or -specification, or statement) assumed by :n:`@ident` and we say that :n:`@ident` -has type :n:`@type`. - -.. _Axiom: - -.. cmd:: @assumption_token {? Inline {? ( @num ) } } {| {+ ( @assumpt ) } | @assumpt } - :name: Axiom; Axioms; Conjecture; Conjectures; Hypothesis; Hypotheses; Parameter; Parameters; Variable; Variables - - .. insertprodn assumption_token of_type - - .. prodn:: - assumption_token ::= {| Axiom | Axioms } - | {| Conjecture | Conjectures } - | {| Parameter | Parameters } - | {| Hypothesis | Hypotheses } - | {| Variable | Variables } - assumpt ::= {+ @ident_decl } @of_type - ident_decl ::= @ident {? @univ_decl } - of_type ::= {| : | :> | :>> } @type - - These commands bind one or more :n:`@ident`\(s) to specified :n:`@type`\(s) as their specifications in - the global context. The fact asserted by the :n:`@type` (or, equivalently, the existence - of an object of this type) is accepted as a postulate. - - :cmd:`Axiom`, :cmd:`Conjecture`, :cmd:`Parameter` and their plural forms - are equivalent. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident`\s accessible by :cmd:`Import` and its variants - only through their fully qualified names. - - Similarly, :cmd:`Hypothesis`, :cmd:`Variable` and their plural forms are equivalent. Outside - of a section, these are equivalent to :n:`Local Parameter`. Inside a section, the - :n:`@ident`\s defined are only accessible within the section. When the current section - is closed, the :n:`@ident`\(s) become undefined and every object depending on them will be explicitly - parameterized (i.e., the variables are *discharged*). See Section :ref:`section-mechanism`. - - The :n:`Inline` clause is only relevant inside functors. See :cmd:`Module`. - -.. example:: Simple assumptions - - .. coqtop:: reset in - - Parameter X Y : Set. - Parameter (R : X -> Y -> Prop) (S : Y -> X -> Prop). - Axiom R_S_inv : forall x y, R x y <-> S y x. - -.. exn:: @ident already exists. - :name: @ident already exists. (Axiom) - :undocumented: - -.. warn:: @ident is declared as a local axiom - - Warning generated when using :cmd:`Variable` or its equivalent - instead of :n:`Local Parameter` or its equivalent. - -.. note:: - We advise using the commands :cmd:`Axiom`, :cmd:`Conjecture` and - :cmd:`Hypothesis` (and their plural forms) for logical postulates (i.e. when - the assertion :n:`@type` is of sort :g:`Prop`), and to use the commands - :cmd:`Parameter` and :cmd:`Variable` (and their plural forms) in other cases - (corresponding to the declaration of an abstract object of the given type). - -.. _gallina-definitions: - -Definitions ------------ - -Definitions extend the environment with associations of names to terms. -A definition can be seen as a way to give a meaning to a name or as a -way to abbreviate a term. In any case, the name can later be replaced at -any time by its definition. - -The operation of unfolding a name into its definition is called -:math:`\delta`-conversion (see Section :ref:`delta-reduction`). A -definition is accepted by the system if and only if the defined term is -well-typed in the current context of the definition and if the name is -not already used. The name defined by the definition is called a -*constant* and the term it refers to is its *body*. A definition has a -type which is the type of its body. - -A formal presentation of constants and environments is given in -Section :ref:`typing-rules`. - -.. cmd:: {| Definition | Example } @ident_decl @def_body - :name: Definition; Example - - .. insertprodn def_body def_body - - .. prodn:: - def_body ::= {* @binder } {? : @type } := {? @reduce } @term - | {* @binder } : @type - - These commands bind :n:`@term` to the name :n:`@ident` in the environment, - provided that :n:`@term` is well-typed. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident` accessible by :cmd:`Import` and its variants - only through their fully qualified names. - If :n:`@reduce` is present then :n:`@ident` is bound to the result of the specified - computation on :n:`@term`. - - These commands also support the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`program` and - :attr:`canonical` attributes. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - The form :n:`Definition @ident : @type := @term` checks that the type of :n:`@term` - is definitionally equal to :n:`@type`, and registers :n:`@ident` as being of type - :n:`@type`, and bound to value :n:`@term`. - - The form :n:`Definition @ident {* @binder } : @type := @term` is equivalent to - :n:`Definition @ident : forall {* @binder }, @type := fun {* @binder } => @term`. - - .. seealso:: :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`. - - .. exn:: @ident already exists. - :name: @ident already exists. (Definition) - :undocumented: - - .. exn:: The term @term has type @type while it is expected to have type @type'. - :undocumented: - -.. _gallina-inductive-definitions: - -Inductive types ---------------- - -.. cmd:: Inductive @inductive_definition {* with @inductive_definition } - - .. insertprodn inductive_definition constructor - - .. prodn:: - inductive_definition ::= {? > } @ident_decl {* @binder } {? %| {* @binder } } {? : @type } {? := {? @constructors_or_record } } {? @decl_notations } - constructors_or_record ::= {? %| } {+| @constructor } - | {? @ident } %{ {*; @record_field } %} - constructor ::= @ident {* @binder } {? @of_type } - - This command defines one or more - inductive types and its constructors. Coq generates destructors - depending on the universe that the inductive type belongs to. - - The destructors are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, - :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``, which - respectively correspond to elimination principles on :g:`Type`, :g:`Prop`, - :g:`Set` and :g:`SProp`. The type of the destructors - expresses structural induction/recursion principles over objects of - type :n:`@ident`. The constant :n:`@ident`\ ``_ind`` is always - generated, whereas :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_rect`` - may be impossible to derive (for example, when :n:`@ident` is a - proposition). - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - Mutually inductive types can be defined by including multiple :n:`@inductive_definition`\s. - The :n:`@ident`\s are simultaneously added to the environment before the types of constructors are checked. - Each :n:`@ident` can be used independently thereafter. - See :ref:`mutually_inductive_types`. - - If the entire inductive definition is parameterized with :n:`@binder`\s, the parameters correspond - to a local context in which the entire set of inductive declarations is interpreted. - For this reason, the parameters must be strictly the same for each inductive type. - See :ref:`parametrized-inductive-types`. - - Constructor :n:`@ident`\s can come with :n:`@binder`\s, in which case - the actual type of the constructor is :n:`forall {* @binder }, @type`. - - .. exn:: Non strictly positive occurrence of @ident in @type. - - The types of the constructors have to satisfy a *positivity condition* - (see Section :ref:`positivity`). This condition ensures the soundness of - the inductive definition. The positivity checking can be disabled using - the :flag:`Positivity Checking` flag (see :ref:`controlling-typing-flags`). - - .. exn:: The conclusion of @type is not valid; it must be built from @ident. - - The conclusion of the type of the constructors must be the inductive type - :n:`@ident` being defined (or :n:`@ident` applied to arguments in - the case of annotated inductive types — cf. next section). - -The following subsections show examples of simple inductive types, -simple annotated inductive types, simple parametric inductive types, -mutually inductive types and private (matching) inductive types. - -.. _simple-inductive-types: - -Simple inductive types -~~~~~~~~~~~~~~~~~~~~~~ - -A simple inductive type belongs to a universe that is a simple :n:`@sort`. - -.. example:: - - The set of natural numbers is defined as: - - .. coqtop:: reset all - - Inductive nat : Set := - | O : nat - | S : nat -> nat. - - The type nat is defined as the least :g:`Set` containing :g:`O` and closed by - the :g:`S` constructor. The names :g:`nat`, :g:`O` and :g:`S` are added to the - environment. - - This definition generates four elimination principles: - :g:`nat_rect`, :g:`nat_ind`, :g:`nat_rec` and :g:`nat_sind`. The type of :g:`nat_ind` is: - - .. coqtop:: all - - Check nat_ind. - - This is the well known structural induction principle over natural - numbers, i.e. the second-order form of Peano’s induction principle. It - allows proving universal properties of natural numbers (:g:`forall - n:nat, P n`) by induction on :g:`n`. - - The types of :g:`nat_rect`, :g:`nat_rec` and :g:`nat_sind` are similar, except that they - apply to, respectively, :g:`(P:nat->Type)`, :g:`(P:nat->Set)` and :g:`(P:nat->SProp)`. They correspond to - primitive induction principles (allowing dependent types) respectively - over sorts ```Type``, ``Set`` and ``SProp``. - -In the case where inductive types don't have annotations (the next section -gives an example of annotations), a constructor can be defined -by giving the type of its arguments alone. - -.. example:: - - .. coqtop:: reset none - - Reset nat. - - .. coqtop:: in - - Inductive nat : Set := O | S (_:nat). - -Simple annotated inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In annotated inductive types, the universe where the inductive type -is defined is no longer a simple :n:`@sort`, but what is called an arity, -which is a type whose conclusion is a :n:`@sort`. - -.. example:: - - As an example of annotated inductive types, let us define the - :g:`even` predicate: - - .. coqtop:: all - - Inductive even : nat -> Prop := - | even_0 : even O - | even_SS : forall n:nat, even n -> even (S (S n)). - - The type :g:`nat->Prop` means that :g:`even` is a unary predicate (inductively - defined) over natural numbers. The type of its two constructors are the - defining clauses of the predicate :g:`even`. The type of :g:`even_ind` is: - - .. coqtop:: all - - Check even_ind. - - From a mathematical point of view, this asserts that the natural numbers satisfying - the predicate :g:`even` are exactly in the smallest set of naturals satisfying the - clauses :g:`even_0` or :g:`even_SS`. This is why, when we want to prove any - predicate :g:`P` over elements of :g:`even`, it is enough to prove it for :g:`O` - and to prove that if any natural number :g:`n` satisfies :g:`P` its double - successor :g:`(S (S n))` satisfies also :g:`P`. This is analogous to the - structural induction principle we got for :g:`nat`. - -.. _parametrized-inductive-types: - -Parameterized inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the previous example, each constructor introduces a different -instance of the predicate :g:`even`. In some cases, all the constructors -introduce the same generic instance of the inductive definition, in -which case, instead of an annotation, we use a context of parameters -which are :n:`@binder`\s shared by all the constructors of the definition. - -Parameters differ from inductive type annotations in that the -conclusion of each type of constructor invokes the inductive type with -the same parameter values of its specification. - -.. example:: - - A typical example is the definition of polymorphic lists: - - .. coqtop:: all - - Inductive list (A:Set) : Set := - | nil : list A - | cons : A -> list A -> list A. - - In the type of :g:`nil` and :g:`cons`, we write ":g:`list A`" and not - just ":g:`list`". The constructors :g:`nil` and :g:`cons` have these types: - - .. coqtop:: all - - Check nil. - Check cons. - - Observe that the destructors are also quantified with :g:`(A:Set)`, for example: - - .. coqtop:: all - - Check list_ind. - - Once again, the types of the constructor arguments and of the conclusion can be omitted: - - .. coqtop:: none - - Reset list. - - .. coqtop:: in - - Inductive list (A:Set) : Set := nil | cons (_:A) (_:list A). - -.. note:: - + The constructor type can - recursively invoke the inductive definition on an argument which is not - the parameter itself. - - One can define : - - .. coqtop:: all - - Inductive list2 (A:Set) : Set := - | nil2 : list2 A - | cons2 : A -> list2 (A*A) -> list2 A. - - that can also be written by specifying only the type of the arguments: - - .. coqtop:: all reset - - Inductive list2 (A:Set) : Set := - | nil2 - | cons2 (_:A) (_:list2 (A*A)). - - But the following definition will give an error: - - .. coqtop:: all - - Fail Inductive listw (A:Set) : Set := - | nilw : listw (A*A) - | consw : A -> listw (A*A) -> listw (A*A). - - because the conclusion of the type of constructors should be :g:`listw A` - in both cases. - - + A parameterized inductive definition can be defined using annotations - instead of parameters but it will sometimes give a different (bigger) - sort for the inductive definition and will produce a less convenient - rule for case elimination. - -.. flag:: Uniform Inductive Parameters - - When this flag is set (it is off by default), - inductive definitions are abstracted over their parameters - before type checking constructors, allowing to write: - - .. coqtop:: all - - Set Uniform Inductive Parameters. - Inductive list3 (A:Set) : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - - This behavior is essentially equivalent to starting a new section - and using :cmd:`Context` to give the uniform parameters, like so - (cf. :ref:`section-mechanism`): - - .. coqtop:: all reset - - Section list3. - Context (A:Set). - Inductive list3 : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - End list3. - - For finer control, you can use a ``|`` between the uniform and - the non-uniform parameters: - - .. coqtop:: in reset - - Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop - := Acc_in : (forall y, R y x -> Acc y) -> Acc x. - - The flag can then be seen as deciding whether the ``|`` is at the - beginning (when the flag is unset) or at the end (when it is set) - of the parameters when not explicitly given. - -.. seealso:: - Section :ref:`inductive-definitions` and the :tacn:`induction` tactic. - -.. _mutually_inductive_types: - -Mutually defined inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. example:: Mutually defined inductive types - - A typical example of mutually inductive data types is trees and - forests. We assume two types :g:`A` and :g:`B` that are given as variables. The types can - be declared like this: - - .. coqtop:: in - - Parameters A B : Set. - - Inductive tree : Set := node : A -> forest -> tree - - with forest : Set := - | leaf : B -> forest - | cons : tree -> forest -> forest. - - This declaration automatically generates eight induction principles. They are not the most - general principles, but they correspond to each inductive part seen as a single inductive definition. - - To illustrate this point on our example, here are the types of :g:`tree_rec` - and :g:`forest_rec`. - - .. coqtop:: all - - Check tree_rec. - - Check forest_rec. - - Assume we want to parameterize our mutual inductive definitions with the - two type variables :g:`A` and :g:`B`, the declaration should be - done as follows: - - .. coqdoc:: - - Inductive tree (A B:Set) : Set := node : A -> forest A B -> tree A B - - with forest (A B:Set) : Set := - | leaf : B -> forest A B - | cons : tree A B -> forest A B -> forest A B. - - Assume we define an inductive definition inside a section - (cf. :ref:`section-mechanism`). When the section is closed, the variables - declared in the section and occurring free in the declaration are added as - parameters to the inductive definition. - -.. seealso:: - A generic command :cmd:`Scheme` is useful to build automatically various - mutual induction principles. - -Private (matching) inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attr:: private(matching) - - This attribute can be used to forbid the use of the :g:`match` - construct on objects of this inductive type outside of the module - where it is defined. There is also a legacy syntax using the - ``Private`` prefix (cf. :n:`@legacy_attr`). - - The main use case of private (matching) inductive types is to emulate - quotient types / higher-order inductive types in projects such as - the `HoTT library `_. - -.. example:: - - .. coqtop:: all - - Module Foo. - #[ private(matching) ] Inductive my_nat := my_O : my_nat | my_S : my_nat -> my_nat. - Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - End Foo. - Import Foo. - Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - Variants ~~~~~~~~ @@ -983,470 +21,3 @@ Variants .. exn:: The @num th argument of @ident must be @ident in @type. :undocumented: - -.. _coinductive-types: - -Co-inductive types ------------------- - -The objects of an inductive type are well-founded with respect to the -constructors of the type. In other words, such objects contain only a -*finite* number of constructors. Co-inductive types arise from relaxing -this condition, and admitting types whose objects contain an infinity of -constructors. Infinite objects are introduced by a non-ending (but -effective) process of construction, defined in terms of the constructors -of the type. - -.. cmd:: CoInductive @inductive_definition {* with @inductive_definition } - - This command introduces a co-inductive type. - The syntax of the command is the same as the command :cmd:`Inductive`. - No principle of induction is derived from the definition of a co-inductive - type, since such principles only make sense for inductive types. - For co-inductive types, the only elimination principle is case analysis. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - -.. example:: - - The type of infinite sequences of natural numbers, usually called streams, - is an example of a co-inductive type. - - .. coqtop:: in - - CoInductive Stream : Set := Seq : nat -> Stream -> Stream. - - The usual destructors on streams :g:`hd:Stream->nat` and :g:`tl:Str->Str` - can be defined as follows: - - .. coqtop:: in - - Definition hd (x:Stream) := let (a,s) := x in a. - Definition tl (x:Stream) := let (a,s) := x in s. - -Definitions of co-inductive predicates and blocks of mutually -co-inductive definitions are also allowed. - -.. example:: - - The extensional equality on streams is an example of a co-inductive type: - - .. coqtop:: in - - CoInductive EqSt : Stream -> Stream -> Prop := - eqst : forall s1 s2:Stream, - hd s1 = hd s2 -> EqSt (tl s1) (tl s2) -> EqSt s1 s2. - - In order to prove the extensional equality of two streams :g:`s1` and :g:`s2` - we have to construct an infinite proof of equality, that is, an infinite - object of type :g:`(EqSt s1 s2)`. We will see how to introduce infinite - objects in Section :ref:`cofixpoint`. - -Caveat -~~~~~~ - -The ability to define co-inductive types by constructors, hereafter called -*positive co-inductive types*, is known to break subject reduction. The story is -a bit long: this is due to dependent pattern-matching which implies -propositional η-equality, which itself would require full η-conversion for -subject reduction to hold, but full η-conversion is not acceptable as it would -make type checking undecidable. - -Since the introduction of primitive records in Coq 8.5, an alternative -presentation is available, called *negative co-inductive types*. This consists -in defining a co-inductive type as a primitive record type through its -projections. Such a technique is akin to the *co-pattern* style that can be -found in e.g. Agda, and preserves subject reduction. - -The above example can be rewritten in the following way. - -.. coqtop:: none - - Reset Stream. - -.. coqtop:: all - - Set Primitive Projections. - CoInductive Stream : Set := Seq { hd : nat; tl : Stream }. - CoInductive EqSt (s1 s2: Stream) : Prop := eqst { - eqst_hd : hd s1 = hd s2; - eqst_tl : EqSt (tl s1) (tl s2); - }. - -Some properties that hold over positive streams are lost when going to the -negative presentation, typically when they imply equality over streams. -For instance, propositional η-equality is lost when going to the negative -presentation. It is nonetheless logically consistent to recover it through an -axiom. - -.. coqtop:: all - - Axiom Stream_eta : forall s: Stream, s = Seq (hd s) (tl s). - -More generally, as in the case of positive coinductive types, it is consistent -to further identify extensional equality of coinductive types with propositional -equality: - -.. coqtop:: all - - Axiom Stream_ext : forall (s1 s2: Stream), EqSt s1 s2 -> s1 = s2. - -As of Coq 8.9, it is now advised to use negative co-inductive types rather than -their positive counterparts. - -.. seealso:: - :ref:`primitive_projections` for more information about negative - records and primitive projections. - - -Definition of recursive functions ---------------------------------- - -Definition of functions by recursion over inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This section describes the primitive form of definition by recursion over -inductive objects. See the :cmd:`Function` command for more advanced -constructions. - -.. _Fixpoint: - -.. cmd:: Fixpoint @fix_definition {* with @fix_definition } - - .. insertprodn fix_definition fix_definition - - .. prodn:: - fix_definition ::= @ident_decl {* @binder } {? @fixannot } {? : @type } {? := @term } {? @decl_notations } - - This command allows defining functions by pattern matching over inductive - objects using a fixed point construction. The meaning of this declaration is - to define :n:`@ident` as a recursive function with arguments specified by - the :n:`@binder`\s such that :n:`@ident` applied to arguments - corresponding to these :n:`@binder`\s has type :n:`@type`, and is - equivalent to the expression :n:`@term`. The type of :n:`@ident` is - consequently :n:`forall {* @binder }, @type` and its value is equivalent - to :n:`fun {* @binder } => @term`. - - To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical - constraints on a special argument called the decreasing argument. They - are needed to ensure that the :cmd:`Fixpoint` definition always terminates. - The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to - let the user tell the system which argument decreases along the recursive calls. - - The :n:`{struct @ident}` annotation may be left implicit, in which case the - system successively tries arguments from left to right until it finds one - that satisfies the decreasing condition. - - :cmd:`Fixpoint` without the :attr:`program` attribute does not support the - :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. - - The :n:`with` clause allows simultaneously defining several mutual fixpoints. - It is especially useful when defining functions over mutually defined - inductive types. Example: :ref:`Mutual Fixpoints`. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - .. note:: - - + Some fixpoints may have several arguments that fit as decreasing - arguments, and this choice influences the reduction of the fixpoint. - Hence an explicit annotation must be used if the leftmost decreasing - argument is not the desired one. Writing explicit annotations can also - speed up type checking of large mutual fixpoints. - - + In order to keep the strong normalization property, the fixed point - reduction will only be performed when the argument in position of the - decreasing argument (which type should be in an inductive definition) - starts with a constructor. - - - .. example:: - - One can define the addition function as : - - .. coqtop:: all - - Fixpoint add (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (add p m) - end. - - The match operator matches a value (here :g:`n`) with the various - constructors of its (inductive) type. The remaining arguments give the - respective values to be returned, as functions of the parameters of the - corresponding constructor. Thus here when :g:`n` equals :g:`O` we return - :g:`m`, and when :g:`n` equals :g:`(S p)` we return :g:`(S (add p m))`. - - The match operator is formally described in - Section :ref:`match-construction`. - The system recognizes that in the inductive call :g:`(add p m)` the first - argument actually decreases because it is a *pattern variable* coming - from :g:`match n with`. - - .. example:: - - The following definition is not correct and generates an error message: - - .. coqtop:: all - - Fail Fixpoint wrongplus (n m:nat) {struct n} : nat := - match m with - | O => n - | S p => S (wrongplus n p) - end. - - because the declared decreasing argument :g:`n` does not actually - decrease in the recursive call. The function computing the addition over - the second argument should rather be written: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct m} : nat := - match m with - | O => n - | S p => S (plus n p) - end. - - .. example:: - - The recursive call may not only be on direct subterms of the recursive - variable :g:`n` but also on a deeper subterm and we can directly write - the function :g:`mod2` which gives the remainder modulo 2 of a natural - number. - - .. coqtop:: all - - Fixpoint mod2 (n:nat) : nat := - match n with - | O => O - | S p => match p with - | O => S O - | S q => mod2 q - end - end. - -.. _example_mutual_fixpoints: - - .. example:: Mutual fixpoints - - The size of trees and forests can be defined the following way: - - .. coqtop:: all - - Fixpoint tree_size (t:tree) : nat := - match t with - | node a f => S (forest_size f) - end - with forest_size (f:forest) : nat := - match f with - | leaf b => 1 - | cons t f' => (tree_size t + forest_size f') - end. - -.. _cofixpoint: - -Definitions of recursive objects in co-inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. cmd:: CoFixpoint @cofix_definition {* with @cofix_definition } - - .. insertprodn cofix_definition cofix_definition - - .. prodn:: - cofix_definition ::= @ident_decl {* @binder } {? : @type } {? := @term } {? @decl_notations } - - This command introduces a method for constructing an infinite object of a - coinductive type. For example, the stream containing all natural numbers can - be introduced applying the following method to the number :g:`O` (see - Section :ref:`coinductive-types` for the definition of :g:`Stream`, :g:`hd` - and :g:`tl`): - - .. coqtop:: all - - CoFixpoint from (n:nat) : Stream := Seq n (from (S n)). - - Unlike recursive definitions, there is no decreasing argument in a - co-recursive definition. To be admissible, a method of construction must - provide at least one extra constructor of the infinite object for each - iteration. A syntactical guard condition is imposed on co-recursive - definitions in order to ensure this: each recursive call in the - definition must be protected by at least one constructor, and only by - constructors. That is the case in the former definition, where the single - recursive call of :g:`from` is guarded by an application of :g:`Seq`. - On the contrary, the following recursive function does not satisfy the - guard condition: - - .. coqtop:: all - - Fail CoFixpoint filter (p:nat -> bool) (s:Stream) : Stream := - if p (hd s) then Seq (hd s) (filter p (tl s)) else filter p (tl s). - - The elimination of co-recursive definition is done lazily, i.e. the - definition is expanded only when it occurs at the head of an application - which is the argument of a case analysis expression. In any other - context, it is considered as a canonical expression which is completely - evaluated. We can test this using the command :cmd:`Eval`, which computes - the normal forms of a term: - - .. coqtop:: all - - Eval compute in (from 0). - Eval compute in (hd (from 0)). - Eval compute in (tl (from 0)). - - As in the :cmd:`Fixpoint` command, the :n:`with` clause allows simultaneously - defining several mutual cofixpoints. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - -.. _Computations: - -Computations ------------- - -.. insertprodn reduce pattern_occ - -.. prodn:: - reduce ::= Eval @red_expr in - red_expr ::= red - | hnf - | simpl {? @delta_flag } {? @ref_or_pattern_occ } - | cbv {? @strategy_flag } - | cbn {? @strategy_flag } - | lazy {? @strategy_flag } - | compute {? @delta_flag } - | vm_compute {? @ref_or_pattern_occ } - | native_compute {? @ref_or_pattern_occ } - | unfold {+, @unfold_occ } - | fold {+ @one_term } - | pattern {+, @pattern_occ } - | @ident - delta_flag ::= {? - } [ {+ @smart_qualid } ] - strategy_flag ::= {+ @red_flags } - | @delta_flag - red_flags ::= beta - | iota - | match - | fix - | cofix - | zeta - | delta {? @delta_flag } - ref_or_pattern_occ ::= @smart_qualid {? at @occs_nums } - | @one_term {? at @occs_nums } - occs_nums ::= {+ {| @num | @ident } } - | - {| @num | @ident } {* @int_or_var } - int_or_var ::= @int - | @ident - unfold_occ ::= @smart_qualid {? at @occs_nums } - pattern_occ ::= @one_term {? at @occs_nums } - -See :ref:`Conversion-rules`. - -.. todo:: Add text here - -.. _Assertions: - -Assertions and proofs ---------------------- - -An assertion states a proposition (or a type) of which the proof (or an -inhabitant of the type) is interactively built using tactics. The interactive -proof mode is described in Chapter :ref:`proofhandling` and the tactics in -Chapter :ref:`Tactics`. The basic assertion command is: - -.. cmd:: @thm_token @ident_decl {* @binder } : @type {* with @ident_decl {* @binder } : @type } - :name: Theorem; Lemma; Fact; Remark; Corollary; Proposition; Property - - .. insertprodn thm_token thm_token - - .. prodn:: - thm_token ::= Theorem - | Lemma - | Fact - | Remark - | Corollary - | Proposition - | Property - - After the statement is asserted, Coq needs a proof. Once a proof of - :n:`@type` under the assumptions represented by :n:`@binder`\s is given and - validated, the proof is generalized into a proof of :n:`forall {* @binder }, @type` and - the theorem is bound to the name :n:`@ident` in the environment. - - Forms using the :n:`with` clause are useful for theorems that are proved by simultaneous induction - over a mutually inductive assumption, or that assert mutually dependent - statements in some mutual co-inductive type. It is equivalent to - :cmd:`Fixpoint` or :cmd:`CoFixpoint` but using tactics to build the proof of - the statements (or the body of the specification, depending on the point of - view). The inductive or co-inductive types on which the induction or - coinduction has to be done is assumed to be non ambiguous and is guessed by - the system. - - Like in a :cmd:`Fixpoint` or :cmd:`CoFixpoint` definition, the induction hypotheses - have to be used on *structurally smaller* arguments (for a :cmd:`Fixpoint`) or - be *guarded by a constructor* (for a :cmd:`CoFixpoint`). The verification that - recursive proof arguments are correct is done only at the time of registering - the lemma in the environment. To know if the use of induction hypotheses is - correct at some time of the interactive development of a proof, use the - command :cmd:`Guarded`. - - .. exn:: The term @term has type @type which should be Set, Prop or Type. - :undocumented: - - .. exn:: @ident already exists. - :name: @ident already exists. (Theorem) - - The name you provided is already defined. You have then to choose - another name. - - .. exn:: Nested proofs are not allowed unless you turn the Nested Proofs Allowed flag on. - - You are asserting a new statement while already being in proof editing mode. - This feature, called nested proofs, is disabled by default. - To activate it, turn the :flag:`Nested Proofs Allowed` flag on. - -Proofs start with the keyword :cmd:`Proof`. Then Coq enters the proof editing mode -until the proof is completed. In proof editing mode, the user primarily enters -tactics, which are described in chapter :ref:`Tactics`. The user may also enter -commands to manage the proof editing mode. They are described in Chapter -:ref:`proofhandling`. - -When the proof is complete, use the :cmd:`Qed` command so the kernel verifies -the proof and adds it to the environment. - -.. note:: - - #. Several statements can be simultaneously asserted provided the - :flag:`Nested Proofs Allowed` flag was turned on. - - #. Not only other assertions but any vernacular command can be given - while in the process of proving a given assertion. In this case, the - command is understood as if it would have been given before the - statements still to be proved. Nonetheless, this practice is discouraged - and may stop working in future versions. - - #. Proofs ended by :cmd:`Qed` are declared opaque. Their content cannot be - unfolded (see :ref:`performingcomputations`), thus - realizing some form of *proof-irrelevance*. To be able to unfold a - proof, the proof should be ended by :cmd:`Defined`. - - #. :cmd:`Proof` is recommended but can currently be omitted. On the opposite - side, :cmd:`Qed` (or :cmd:`Defined`) is mandatory to validate a proof. - - #. One can also use :cmd:`Admitted` in place of :cmd:`Qed` to turn the - current asserted statement into an axiom and exit the proof editing mode. - -.. [1] - Except if the inductive type is empty in which case there is no - equation that can be used to infer the return type. -- cgit v1.2.3 From 37b1a35e022a5fb7713e5a1eb5bfd671f1c88248 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 19:49:49 +0200 Subject: Create a new file on Variants. --- doc/sphinx/language/core/variants.rst | 23 ++++++++++++++++++++++ .../language/gallina-specification-language.rst | 23 ---------------------- 2 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 doc/sphinx/language/core/variants.rst delete mode 100644 doc/sphinx/language/gallina-specification-language.rst diff --git a/doc/sphinx/language/core/variants.rst b/doc/sphinx/language/core/variants.rst new file mode 100644 index 0000000000..ff4212bdd4 --- /dev/null +++ b/doc/sphinx/language/core/variants.rst @@ -0,0 +1,23 @@ +Variants +~~~~~~~~ + +.. cmd:: Variant @variant_definition {* with @variant_definition } + + .. insertprodn variant_definition variant_definition + + .. prodn:: + variant_definition ::= @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? %| } {+| @constructor } {? @decl_notations } + + The :cmd:`Variant` command is similar to the :cmd:`Inductive` command, except + that it disallows recursive definition of types (for instance, lists cannot + be defined using :cmd:`Variant`). No induction scheme is generated for + this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. + + This command supports the :attr:`universes(polymorphic)`, + :attr:`universes(monomorphic)`, :attr:`universes(template)`, + :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, + :attr:`universes(noncumulative)` and :attr:`private(matching)` + attributes. + + .. exn:: The @num th argument of @ident must be @ident in @type. + :undocumented: diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst deleted file mode 100644 index ff4212bdd4..0000000000 --- a/doc/sphinx/language/gallina-specification-language.rst +++ /dev/null @@ -1,23 +0,0 @@ -Variants -~~~~~~~~ - -.. cmd:: Variant @variant_definition {* with @variant_definition } - - .. insertprodn variant_definition variant_definition - - .. prodn:: - variant_definition ::= @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? %| } {+| @constructor } {? @decl_notations } - - The :cmd:`Variant` command is similar to the :cmd:`Inductive` command, except - that it disallows recursive definition of types (for instance, lists cannot - be defined using :cmd:`Variant`). No induction scheme is generated for - this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - .. exn:: The @num th argument of @ident must be @ident in @type. - :undocumented: -- cgit v1.2.3 From fc29e2d171dea78253cb8e11b59eff20a86c0649 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 19:54:36 +0200 Subject: Extract match from Gallina. --- .../language/gallina-specification-language.rst | 1308 -------------------- 1 file changed, 1308 deletions(-) diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst index 353bed1b3d..d9e2c07951 100644 --- a/doc/sphinx/language/gallina-specification-language.rst +++ b/doc/sphinx/language/gallina-specification-language.rst @@ -1,281 +1,3 @@ -.. _gallinaspecificationlanguage: - ------------------------------------- - The Gallina specification language ------------------------------------- - -This chapter describes Gallina, the specification language of Coq. It allows -developing mathematical theories and to prove specifications of programs. The -theories are built from axioms, hypotheses, parameters, lemmas, theorems and -definitions of constants, functions, predicates and sets. - -.. _term: - -Terms -===== - -.. _gallina-identifiers: - -Qualified identifiers and simple identifiers --------------------------------------------- - -.. insertprodn qualid field_ident - -.. prodn:: - qualid ::= @ident {* @field_ident } - field_ident ::= .@ident - -*Qualified identifiers* (:n:`@qualid`) denote *global constants* -(definitions, lemmas, theorems, remarks or facts), *global variables* -(parameters or axioms), *inductive types* or *constructors of inductive -types*. *Simple identifiers* (or shortly :n:`@ident`) are a syntactic subset -of qualified identifiers. Identifiers may also denote *local variables*, -while qualified identifiers do not. - -Field identifiers, written :n:`@field_ident`, are identifiers prefixed by -`.` (dot) with no blank between the dot and the identifier. - - -Numerals and strings --------------------- - -.. insertprodn primitive_notations primitive_notations - -.. prodn:: - primitive_notations ::= @numeral - | @string - -Numerals and strings have no predefined semantics in the calculus. They are -merely notations that can be bound to objects through the notation mechanism -(see Chapter :ref:`syntax-extensions-and-notation-scopes` for details). -Initially, numerals are bound to Peano’s representation of natural -numbers (see :ref:`datatypes`). - -.. note:: - - Negative integers are not at the same level as :n:`@num`, for this - would make precedence unnatural. - -.. index:: - single: Set (sort) - single: SProp - single: Prop - single: Type - -Sorts ------ - -.. insertprodn sort univ_constraint - -.. prodn:: - sort ::= Set - | Prop - | SProp - | Type - | Type @%{ _ %} - | Type @%{ @universe %} - universe ::= max ( {+, @universe_expr } ) - | @universe_expr - universe_expr ::= @universe_name {? + @num } - universe_name ::= @qualid - | Set - | Prop - univ_annot ::= @%{ {* @universe_level } %} - universe_level ::= Set - | Prop - | Type - | _ - | @qualid - univ_decl ::= @%{ {* @ident } {? + } {? %| {*, @univ_constraint } {? + } } %} - univ_constraint ::= @universe_name {| < | = | <= } @universe_name - -There are four sorts :g:`SProp`, :g:`Prop`, :g:`Set` and :g:`Type`. - -- :g:`SProp` is the universe of *definitionally irrelevant - propositions* (also called *strict propositions*). - -- :g:`Prop` is the universe of *logical propositions*. The logical propositions - themselves are typing the proofs. We denote propositions by :n:`@form`. - This constitutes a semantic subclass of the syntactic class :n:`@term`. - -- :g:`Set` is the universe of *program types* or *specifications*. The - specifications themselves are typing the programs. We denote - specifications by :n:`@specif`. This constitutes a semantic subclass of - the syntactic class :n:`@term`. - -- :g:`Type` is the type of sorts. - -More on sorts can be found in Section :ref:`sorts`. - -.. _binders: - -Binders -------- - -.. insertprodn open_binders binder - -.. prodn:: - open_binders ::= {+ @name } : @term - | {+ @binder } - name ::= _ - | @ident - binder ::= @name - | ( {+ @name } : @type ) - | ( @name {? : @type } := @term ) - | @implicit_binders - | @generalizing_binder - | ( @name : @type %| @term ) - | ' @pattern0 - -Various constructions such as :g:`fun`, :g:`forall`, :g:`fix` and :g:`cofix` -*bind* variables. A binding is represented by an identifier. If the binding -variable is not used in the expression, the identifier can be replaced by the -symbol :g:`_`. When the type of a bound variable cannot be synthesized by the -system, it can be specified with the notation :n:`(@ident : @type)`. There is also -a notation for a sequence of binding variables sharing the same type: -:n:`({+ @ident} : @type)`. A -binder can also be any pattern prefixed by a quote, e.g. :g:`'(x,y)`. - -Some constructions allow the binding of a variable to value. This is -called a “let-binder”. The entry :n:`@binder` of the grammar accepts -either an assumption binder as defined above or a let-binder. The notation in -the latter case is :n:`(@ident := @term)`. In a let-binder, only one -variable can be introduced at the same time. It is also possible to give -the type of the variable as follows: -:n:`(@ident : @type := @term)`. - -Lists of :n:`@binder`\s are allowed. In the case of :g:`fun` and :g:`forall`, -it is intended that at least one binder of the list is an assumption otherwise -fun and forall gets identical. Moreover, parentheses can be omitted in -the case of a single sequence of bindings sharing the same type (e.g.: -:g:`fun (x y z : A) => t` can be shortened in :g:`fun x y z : A => t`). - -.. index:: fun ... => ... - -Abstractions: fun ------------------ - -The expression :n:`fun @ident : @type => @term` defines the -*abstraction* of the variable :n:`@ident`, of type :n:`@type`, over the term -:n:`@term`. It denotes a function of the variable :n:`@ident` that evaluates to -the expression :n:`@term` (e.g. :g:`fun x : A => x` denotes the identity -function on type :g:`A`). The keyword :g:`fun` can be followed by several -binders as given in Section :ref:`binders`. Functions over -several variables are equivalent to an iteration of one-variable -functions. For instance the expression -:n:`fun {+ @ident__i } : @type => @term` -denotes the same function as :n:`{+ fun @ident__i : @type => } @term`. If -a let-binder occurs in -the list of binders, it is expanded to a let-in definition (see -Section :ref:`let-in`). - -.. index:: forall - -Products: forall ----------------- - -.. insertprodn term_forall_or_fun term_forall_or_fun - -.. prodn:: - term_forall_or_fun ::= forall @open_binders , @term - | fun @open_binders => @term - -The expression :n:`forall @ident : @type, @term` denotes the -*product* of the variable :n:`@ident` of type :n:`@type`, over the term :n:`@term`. -As for abstractions, :g:`forall` is followed by a binder list, and products -over several variables are equivalent to an iteration of one-variable -products. Note that :n:`@term` is intended to be a type. - -If the variable :n:`@ident` occurs in :n:`@term`, the product is called -*dependent product*. The intention behind a dependent product -:g:`forall x : A, B` is twofold. It denotes either -the universal quantification of the variable :g:`x` of type :g:`A` -in the proposition :g:`B` or the functional dependent product from -:g:`A` to :g:`B` (a construction usually written -:math:`\Pi_{x:A}.B` in set theory). - -Non dependent product types have a special notation: :g:`A -> B` stands for -:g:`forall _ : A, B`. The *non dependent product* is used both to denote -the propositional implication and function types. - -Applications ------------- - -.. insertprodn term_application arg - -.. prodn:: - term_application ::= @term1 {+ @arg } - | @ @qualid_annotated {+ @term1 } - arg ::= ( @ident := @term ) - | @term1 - -:n:`@term__fun @term` denotes applying the function :n:`@term__fun` to :token:`term`. - -:n:`@term__fun {+ @term__i }` denotes applying -:n:`@term__fun` to the arguments :n:`@term__i`. It is -equivalent to :n:`( … ( @term__fun @term__1 ) … ) @term__n`: -associativity is to the left. - -The notation :n:`(@ident := @term)` for arguments is used for making -explicit the value of implicit arguments (see -Section :ref:`explicit-applications`). - -.. index:: - single: ... : ... (type cast) - single: ... <: ... - single: ... <<: ... - -Type cast ---------- - -.. insertprodn term_cast term_cast - -.. prodn:: - term_cast ::= @term10 <: @term - | @term10 <<: @term - | @term10 : @term - | @term10 :> - -The expression :n:`@term : @type` is a type cast expression. It enforces -the type of :n:`@term` to be :n:`@type`. - -:n:`@term <: @type` locally sets up the virtual machine for checking that -:n:`@term` has type :n:`@type`. - -:n:`@term <<: @type` uses native compilation for checking that :n:`@term` -has type :n:`@type`. - -.. index:: _ - -Inferable subterms ------------------- - -Expressions often contain redundant pieces of information. Subterms that can be -automatically inferred by Coq can be replaced by the symbol ``_`` and Coq will -guess the missing piece of information. - -.. index:: let ... := ... (term) - -.. _let-in: - -Let-in definitions ------------------- - -.. insertprodn term_let term_let - -.. prodn:: - term_let ::= let @name {? : @type } := @term in @term - | let @name {+ @binder } {? : @type } := @term in @term - | let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term - | let ' @pattern := @term {? return @term100 } in @term - | let ' @pattern in @pattern := @term return @term100 in @term - -:n:`let @ident := @term in @term’` -denotes the local binding of :n:`@term` to the variable -:n:`@ident` in :n:`@term`’. There is a syntactic sugar for let-in -definition of functions: :n:`let @ident {+ @binder} := @term in @term’` -stands for :n:`let @ident := fun {+ @binder} => @term in @term’`. - .. index:: match ... with ... Definition by cases: match @@ -420,1033 +142,3 @@ a type with annotations. For this third subcase, both the clauses ``as`` and There are specific notations for case analysis on types with one or two constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). - -.. index:: - single: fix - single: cofix - -Recursive and co-recursive functions: fix and cofix ---------------------------------------------------- - -.. insertprodn term_fix fixannot - -.. prodn:: - term_fix ::= let fix @fix_body in @term - | fix @fix_body {? {+ with @fix_body } for @ident } - fix_body ::= @ident {* @binder } {? @fixannot } {? : @type } := @term - fixannot ::= %{ struct @ident %} - | %{ wf @one_term @ident %} - | %{ measure @one_term {? @ident } {? @one_term } %} - - -The expression ":n:`fix @ident__1 @binder__1 : @type__1 := @term__1 with … with @ident__n @binder__n : @type__n := @term__n for @ident__i`" denotes the -:math:`i`-th component of a block of functions defined by mutual structural -recursion. It is the local counterpart of the :cmd:`Fixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -The association of a single fixpoint and a local definition have a special -syntax: :n:`let fix @ident {* @binder } := @term in` stands for -:n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for co-fixpoints. - -Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` -only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in -commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. - -.. insertprodn term_cofix cofix_body - -.. prodn:: - term_cofix ::= let cofix @cofix_body in @term - | cofix @cofix_body {? {+ with @cofix_body } for @ident } - cofix_body ::= @ident {* @binder } {? : @type } := @term - -The expression -":n:`cofix @ident__1 @binder__1 : @type__1 with … with @ident__n @binder__n : @type__n for @ident__i`" -denotes the :math:`i`-th component of a block of terms defined by a mutual guarded -co-recursion. It is the local counterpart of the :cmd:`CoFixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -.. _vernacular: - -The Vernacular -============== - -.. _gallina-assumptions: - -Assumptions ------------ - -Assumptions extend the environment with axioms, parameters, hypotheses -or variables. An assumption binds an :n:`@ident` to a :n:`@type`. It is accepted -by Coq if and only if this :n:`@type` is a correct type in the environment -preexisting the declaration and if :n:`@ident` was not previously defined in -the same module. This :n:`@type` is considered to be the type (or -specification, or statement) assumed by :n:`@ident` and we say that :n:`@ident` -has type :n:`@type`. - -.. _Axiom: - -.. cmd:: @assumption_token {? Inline {? ( @num ) } } {| {+ ( @assumpt ) } | @assumpt } - :name: Axiom; Axioms; Conjecture; Conjectures; Hypothesis; Hypotheses; Parameter; Parameters; Variable; Variables - - .. insertprodn assumption_token of_type - - .. prodn:: - assumption_token ::= {| Axiom | Axioms } - | {| Conjecture | Conjectures } - | {| Parameter | Parameters } - | {| Hypothesis | Hypotheses } - | {| Variable | Variables } - assumpt ::= {+ @ident_decl } @of_type - ident_decl ::= @ident {? @univ_decl } - of_type ::= {| : | :> | :>> } @type - - These commands bind one or more :n:`@ident`\(s) to specified :n:`@type`\(s) as their specifications in - the global context. The fact asserted by the :n:`@type` (or, equivalently, the existence - of an object of this type) is accepted as a postulate. - - :cmd:`Axiom`, :cmd:`Conjecture`, :cmd:`Parameter` and their plural forms - are equivalent. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident`\s accessible by :cmd:`Import` and its variants - only through their fully qualified names. - - Similarly, :cmd:`Hypothesis`, :cmd:`Variable` and their plural forms are equivalent. Outside - of a section, these are equivalent to :n:`Local Parameter`. Inside a section, the - :n:`@ident`\s defined are only accessible within the section. When the current section - is closed, the :n:`@ident`\(s) become undefined and every object depending on them will be explicitly - parameterized (i.e., the variables are *discharged*). See Section :ref:`section-mechanism`. - - The :n:`Inline` clause is only relevant inside functors. See :cmd:`Module`. - -.. example:: Simple assumptions - - .. coqtop:: reset in - - Parameter X Y : Set. - Parameter (R : X -> Y -> Prop) (S : Y -> X -> Prop). - Axiom R_S_inv : forall x y, R x y <-> S y x. - -.. exn:: @ident already exists. - :name: @ident already exists. (Axiom) - :undocumented: - -.. warn:: @ident is declared as a local axiom - - Warning generated when using :cmd:`Variable` or its equivalent - instead of :n:`Local Parameter` or its equivalent. - -.. note:: - We advise using the commands :cmd:`Axiom`, :cmd:`Conjecture` and - :cmd:`Hypothesis` (and their plural forms) for logical postulates (i.e. when - the assertion :n:`@type` is of sort :g:`Prop`), and to use the commands - :cmd:`Parameter` and :cmd:`Variable` (and their plural forms) in other cases - (corresponding to the declaration of an abstract object of the given type). - -.. _gallina-definitions: - -Definitions ------------ - -Definitions extend the environment with associations of names to terms. -A definition can be seen as a way to give a meaning to a name or as a -way to abbreviate a term. In any case, the name can later be replaced at -any time by its definition. - -The operation of unfolding a name into its definition is called -:math:`\delta`-conversion (see Section :ref:`delta-reduction`). A -definition is accepted by the system if and only if the defined term is -well-typed in the current context of the definition and if the name is -not already used. The name defined by the definition is called a -*constant* and the term it refers to is its *body*. A definition has a -type which is the type of its body. - -A formal presentation of constants and environments is given in -Section :ref:`typing-rules`. - -.. cmd:: {| Definition | Example } @ident_decl @def_body - :name: Definition; Example - - .. insertprodn def_body def_body - - .. prodn:: - def_body ::= {* @binder } {? : @type } := {? @reduce } @term - | {* @binder } : @type - - These commands bind :n:`@term` to the name :n:`@ident` in the environment, - provided that :n:`@term` is well-typed. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident` accessible by :cmd:`Import` and its variants - only through their fully qualified names. - If :n:`@reduce` is present then :n:`@ident` is bound to the result of the specified - computation on :n:`@term`. - - These commands also support the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`program` and - :attr:`canonical` attributes. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - The form :n:`Definition @ident : @type := @term` checks that the type of :n:`@term` - is definitionally equal to :n:`@type`, and registers :n:`@ident` as being of type - :n:`@type`, and bound to value :n:`@term`. - - The form :n:`Definition @ident {* @binder } : @type := @term` is equivalent to - :n:`Definition @ident : forall {* @binder }, @type := fun {* @binder } => @term`. - - .. seealso:: :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`. - - .. exn:: @ident already exists. - :name: @ident already exists. (Definition) - :undocumented: - - .. exn:: The term @term has type @type while it is expected to have type @type'. - :undocumented: - -.. _gallina-inductive-definitions: - -Inductive types ---------------- - -.. cmd:: Inductive @inductive_definition {* with @inductive_definition } - - .. insertprodn inductive_definition constructor - - .. prodn:: - inductive_definition ::= {? > } @ident_decl {* @binder } {? %| {* @binder } } {? : @type } {? := {? @constructors_or_record } } {? @decl_notations } - constructors_or_record ::= {? %| } {+| @constructor } - | {? @ident } %{ {*; @record_field } %} - constructor ::= @ident {* @binder } {? @of_type } - - This command defines one or more - inductive types and its constructors. Coq generates destructors - depending on the universe that the inductive type belongs to. - - The destructors are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, - :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``, which - respectively correspond to elimination principles on :g:`Type`, :g:`Prop`, - :g:`Set` and :g:`SProp`. The type of the destructors - expresses structural induction/recursion principles over objects of - type :n:`@ident`. The constant :n:`@ident`\ ``_ind`` is always - generated, whereas :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_rect`` - may be impossible to derive (for example, when :n:`@ident` is a - proposition). - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - Mutually inductive types can be defined by including multiple :n:`@inductive_definition`\s. - The :n:`@ident`\s are simultaneously added to the environment before the types of constructors are checked. - Each :n:`@ident` can be used independently thereafter. - See :ref:`mutually_inductive_types`. - - If the entire inductive definition is parameterized with :n:`@binder`\s, the parameters correspond - to a local context in which the entire set of inductive declarations is interpreted. - For this reason, the parameters must be strictly the same for each inductive type. - See :ref:`parametrized-inductive-types`. - - Constructor :n:`@ident`\s can come with :n:`@binder`\s, in which case - the actual type of the constructor is :n:`forall {* @binder }, @type`. - - .. exn:: Non strictly positive occurrence of @ident in @type. - - The types of the constructors have to satisfy a *positivity condition* - (see Section :ref:`positivity`). This condition ensures the soundness of - the inductive definition. The positivity checking can be disabled using - the :flag:`Positivity Checking` flag (see :ref:`controlling-typing-flags`). - - .. exn:: The conclusion of @type is not valid; it must be built from @ident. - - The conclusion of the type of the constructors must be the inductive type - :n:`@ident` being defined (or :n:`@ident` applied to arguments in - the case of annotated inductive types — cf. next section). - -The following subsections show examples of simple inductive types, -simple annotated inductive types, simple parametric inductive types, -mutually inductive types and private (matching) inductive types. - -.. _simple-inductive-types: - -Simple inductive types -~~~~~~~~~~~~~~~~~~~~~~ - -A simple inductive type belongs to a universe that is a simple :n:`@sort`. - -.. example:: - - The set of natural numbers is defined as: - - .. coqtop:: reset all - - Inductive nat : Set := - | O : nat - | S : nat -> nat. - - The type nat is defined as the least :g:`Set` containing :g:`O` and closed by - the :g:`S` constructor. The names :g:`nat`, :g:`O` and :g:`S` are added to the - environment. - - This definition generates four elimination principles: - :g:`nat_rect`, :g:`nat_ind`, :g:`nat_rec` and :g:`nat_sind`. The type of :g:`nat_ind` is: - - .. coqtop:: all - - Check nat_ind. - - This is the well known structural induction principle over natural - numbers, i.e. the second-order form of Peano’s induction principle. It - allows proving universal properties of natural numbers (:g:`forall - n:nat, P n`) by induction on :g:`n`. - - The types of :g:`nat_rect`, :g:`nat_rec` and :g:`nat_sind` are similar, except that they - apply to, respectively, :g:`(P:nat->Type)`, :g:`(P:nat->Set)` and :g:`(P:nat->SProp)`. They correspond to - primitive induction principles (allowing dependent types) respectively - over sorts ```Type``, ``Set`` and ``SProp``. - -In the case where inductive types don't have annotations (the next section -gives an example of annotations), a constructor can be defined -by giving the type of its arguments alone. - -.. example:: - - .. coqtop:: reset none - - Reset nat. - - .. coqtop:: in - - Inductive nat : Set := O | S (_:nat). - -Simple annotated inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In annotated inductive types, the universe where the inductive type -is defined is no longer a simple :n:`@sort`, but what is called an arity, -which is a type whose conclusion is a :n:`@sort`. - -.. example:: - - As an example of annotated inductive types, let us define the - :g:`even` predicate: - - .. coqtop:: all - - Inductive even : nat -> Prop := - | even_0 : even O - | even_SS : forall n:nat, even n -> even (S (S n)). - - The type :g:`nat->Prop` means that :g:`even` is a unary predicate (inductively - defined) over natural numbers. The type of its two constructors are the - defining clauses of the predicate :g:`even`. The type of :g:`even_ind` is: - - .. coqtop:: all - - Check even_ind. - - From a mathematical point of view, this asserts that the natural numbers satisfying - the predicate :g:`even` are exactly in the smallest set of naturals satisfying the - clauses :g:`even_0` or :g:`even_SS`. This is why, when we want to prove any - predicate :g:`P` over elements of :g:`even`, it is enough to prove it for :g:`O` - and to prove that if any natural number :g:`n` satisfies :g:`P` its double - successor :g:`(S (S n))` satisfies also :g:`P`. This is analogous to the - structural induction principle we got for :g:`nat`. - -.. _parametrized-inductive-types: - -Parameterized inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the previous example, each constructor introduces a different -instance of the predicate :g:`even`. In some cases, all the constructors -introduce the same generic instance of the inductive definition, in -which case, instead of an annotation, we use a context of parameters -which are :n:`@binder`\s shared by all the constructors of the definition. - -Parameters differ from inductive type annotations in that the -conclusion of each type of constructor invokes the inductive type with -the same parameter values of its specification. - -.. example:: - - A typical example is the definition of polymorphic lists: - - .. coqtop:: all - - Inductive list (A:Set) : Set := - | nil : list A - | cons : A -> list A -> list A. - - In the type of :g:`nil` and :g:`cons`, we write ":g:`list A`" and not - just ":g:`list`". The constructors :g:`nil` and :g:`cons` have these types: - - .. coqtop:: all - - Check nil. - Check cons. - - Observe that the destructors are also quantified with :g:`(A:Set)`, for example: - - .. coqtop:: all - - Check list_ind. - - Once again, the types of the constructor arguments and of the conclusion can be omitted: - - .. coqtop:: none - - Reset list. - - .. coqtop:: in - - Inductive list (A:Set) : Set := nil | cons (_:A) (_:list A). - -.. note:: - + The constructor type can - recursively invoke the inductive definition on an argument which is not - the parameter itself. - - One can define : - - .. coqtop:: all - - Inductive list2 (A:Set) : Set := - | nil2 : list2 A - | cons2 : A -> list2 (A*A) -> list2 A. - - that can also be written by specifying only the type of the arguments: - - .. coqtop:: all reset - - Inductive list2 (A:Set) : Set := - | nil2 - | cons2 (_:A) (_:list2 (A*A)). - - But the following definition will give an error: - - .. coqtop:: all - - Fail Inductive listw (A:Set) : Set := - | nilw : listw (A*A) - | consw : A -> listw (A*A) -> listw (A*A). - - because the conclusion of the type of constructors should be :g:`listw A` - in both cases. - - + A parameterized inductive definition can be defined using annotations - instead of parameters but it will sometimes give a different (bigger) - sort for the inductive definition and will produce a less convenient - rule for case elimination. - -.. flag:: Uniform Inductive Parameters - - When this flag is set (it is off by default), - inductive definitions are abstracted over their parameters - before type checking constructors, allowing to write: - - .. coqtop:: all - - Set Uniform Inductive Parameters. - Inductive list3 (A:Set) : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - - This behavior is essentially equivalent to starting a new section - and using :cmd:`Context` to give the uniform parameters, like so - (cf. :ref:`section-mechanism`): - - .. coqtop:: all reset - - Section list3. - Context (A:Set). - Inductive list3 : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - End list3. - - For finer control, you can use a ``|`` between the uniform and - the non-uniform parameters: - - .. coqtop:: in reset - - Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop - := Acc_in : (forall y, R y x -> Acc y) -> Acc x. - - The flag can then be seen as deciding whether the ``|`` is at the - beginning (when the flag is unset) or at the end (when it is set) - of the parameters when not explicitly given. - -.. seealso:: - Section :ref:`inductive-definitions` and the :tacn:`induction` tactic. - -.. _mutually_inductive_types: - -Mutually defined inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. example:: Mutually defined inductive types - - A typical example of mutually inductive data types is trees and - forests. We assume two types :g:`A` and :g:`B` that are given as variables. The types can - be declared like this: - - .. coqtop:: in - - Parameters A B : Set. - - Inductive tree : Set := node : A -> forest -> tree - - with forest : Set := - | leaf : B -> forest - | cons : tree -> forest -> forest. - - This declaration automatically generates eight induction principles. They are not the most - general principles, but they correspond to each inductive part seen as a single inductive definition. - - To illustrate this point on our example, here are the types of :g:`tree_rec` - and :g:`forest_rec`. - - .. coqtop:: all - - Check tree_rec. - - Check forest_rec. - - Assume we want to parameterize our mutual inductive definitions with the - two type variables :g:`A` and :g:`B`, the declaration should be - done as follows: - - .. coqdoc:: - - Inductive tree (A B:Set) : Set := node : A -> forest A B -> tree A B - - with forest (A B:Set) : Set := - | leaf : B -> forest A B - | cons : tree A B -> forest A B -> forest A B. - - Assume we define an inductive definition inside a section - (cf. :ref:`section-mechanism`). When the section is closed, the variables - declared in the section and occurring free in the declaration are added as - parameters to the inductive definition. - -.. seealso:: - A generic command :cmd:`Scheme` is useful to build automatically various - mutual induction principles. - -Private (matching) inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attr:: private(matching) - - This attribute can be used to forbid the use of the :g:`match` - construct on objects of this inductive type outside of the module - where it is defined. There is also a legacy syntax using the - ``Private`` prefix (cf. :n:`@legacy_attr`). - - The main use case of private (matching) inductive types is to emulate - quotient types / higher-order inductive types in projects such as - the `HoTT library `_. - -.. example:: - - .. coqtop:: all - - Module Foo. - #[ private(matching) ] Inductive my_nat := my_O : my_nat | my_S : my_nat -> my_nat. - Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - End Foo. - Import Foo. - Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - -Variants -~~~~~~~~ - -.. cmd:: Variant @variant_definition {* with @variant_definition } - - .. insertprodn variant_definition variant_definition - - .. prodn:: - variant_definition ::= @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? %| } {+| @constructor } {? @decl_notations } - - The :cmd:`Variant` command is similar to the :cmd:`Inductive` command, except - that it disallows recursive definition of types (for instance, lists cannot - be defined using :cmd:`Variant`). No induction scheme is generated for - this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - .. exn:: The @num th argument of @ident must be @ident in @type. - :undocumented: - -.. _coinductive-types: - -Co-inductive types ------------------- - -The objects of an inductive type are well-founded with respect to the -constructors of the type. In other words, such objects contain only a -*finite* number of constructors. Co-inductive types arise from relaxing -this condition, and admitting types whose objects contain an infinity of -constructors. Infinite objects are introduced by a non-ending (but -effective) process of construction, defined in terms of the constructors -of the type. - -.. cmd:: CoInductive @inductive_definition {* with @inductive_definition } - - This command introduces a co-inductive type. - The syntax of the command is the same as the command :cmd:`Inductive`. - No principle of induction is derived from the definition of a co-inductive - type, since such principles only make sense for inductive types. - For co-inductive types, the only elimination principle is case analysis. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - -.. example:: - - The type of infinite sequences of natural numbers, usually called streams, - is an example of a co-inductive type. - - .. coqtop:: in - - CoInductive Stream : Set := Seq : nat -> Stream -> Stream. - - The usual destructors on streams :g:`hd:Stream->nat` and :g:`tl:Str->Str` - can be defined as follows: - - .. coqtop:: in - - Definition hd (x:Stream) := let (a,s) := x in a. - Definition tl (x:Stream) := let (a,s) := x in s. - -Definitions of co-inductive predicates and blocks of mutually -co-inductive definitions are also allowed. - -.. example:: - - The extensional equality on streams is an example of a co-inductive type: - - .. coqtop:: in - - CoInductive EqSt : Stream -> Stream -> Prop := - eqst : forall s1 s2:Stream, - hd s1 = hd s2 -> EqSt (tl s1) (tl s2) -> EqSt s1 s2. - - In order to prove the extensional equality of two streams :g:`s1` and :g:`s2` - we have to construct an infinite proof of equality, that is, an infinite - object of type :g:`(EqSt s1 s2)`. We will see how to introduce infinite - objects in Section :ref:`cofixpoint`. - -Caveat -~~~~~~ - -The ability to define co-inductive types by constructors, hereafter called -*positive co-inductive types*, is known to break subject reduction. The story is -a bit long: this is due to dependent pattern-matching which implies -propositional η-equality, which itself would require full η-conversion for -subject reduction to hold, but full η-conversion is not acceptable as it would -make type checking undecidable. - -Since the introduction of primitive records in Coq 8.5, an alternative -presentation is available, called *negative co-inductive types*. This consists -in defining a co-inductive type as a primitive record type through its -projections. Such a technique is akin to the *co-pattern* style that can be -found in e.g. Agda, and preserves subject reduction. - -The above example can be rewritten in the following way. - -.. coqtop:: none - - Reset Stream. - -.. coqtop:: all - - Set Primitive Projections. - CoInductive Stream : Set := Seq { hd : nat; tl : Stream }. - CoInductive EqSt (s1 s2: Stream) : Prop := eqst { - eqst_hd : hd s1 = hd s2; - eqst_tl : EqSt (tl s1) (tl s2); - }. - -Some properties that hold over positive streams are lost when going to the -negative presentation, typically when they imply equality over streams. -For instance, propositional η-equality is lost when going to the negative -presentation. It is nonetheless logically consistent to recover it through an -axiom. - -.. coqtop:: all - - Axiom Stream_eta : forall s: Stream, s = Seq (hd s) (tl s). - -More generally, as in the case of positive coinductive types, it is consistent -to further identify extensional equality of coinductive types with propositional -equality: - -.. coqtop:: all - - Axiom Stream_ext : forall (s1 s2: Stream), EqSt s1 s2 -> s1 = s2. - -As of Coq 8.9, it is now advised to use negative co-inductive types rather than -their positive counterparts. - -.. seealso:: - :ref:`primitive_projections` for more information about negative - records and primitive projections. - - -Definition of recursive functions ---------------------------------- - -Definition of functions by recursion over inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This section describes the primitive form of definition by recursion over -inductive objects. See the :cmd:`Function` command for more advanced -constructions. - -.. _Fixpoint: - -.. cmd:: Fixpoint @fix_definition {* with @fix_definition } - - .. insertprodn fix_definition fix_definition - - .. prodn:: - fix_definition ::= @ident_decl {* @binder } {? @fixannot } {? : @type } {? := @term } {? @decl_notations } - - This command allows defining functions by pattern matching over inductive - objects using a fixed point construction. The meaning of this declaration is - to define :n:`@ident` as a recursive function with arguments specified by - the :n:`@binder`\s such that :n:`@ident` applied to arguments - corresponding to these :n:`@binder`\s has type :n:`@type`, and is - equivalent to the expression :n:`@term`. The type of :n:`@ident` is - consequently :n:`forall {* @binder }, @type` and its value is equivalent - to :n:`fun {* @binder } => @term`. - - To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical - constraints on a special argument called the decreasing argument. They - are needed to ensure that the :cmd:`Fixpoint` definition always terminates. - The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to - let the user tell the system which argument decreases along the recursive calls. - - The :n:`{struct @ident}` annotation may be left implicit, in which case the - system successively tries arguments from left to right until it finds one - that satisfies the decreasing condition. - - :cmd:`Fixpoint` without the :attr:`program` attribute does not support the - :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. - - The :n:`with` clause allows simultaneously defining several mutual fixpoints. - It is especially useful when defining functions over mutually defined - inductive types. Example: :ref:`Mutual Fixpoints`. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - .. note:: - - + Some fixpoints may have several arguments that fit as decreasing - arguments, and this choice influences the reduction of the fixpoint. - Hence an explicit annotation must be used if the leftmost decreasing - argument is not the desired one. Writing explicit annotations can also - speed up type checking of large mutual fixpoints. - - + In order to keep the strong normalization property, the fixed point - reduction will only be performed when the argument in position of the - decreasing argument (which type should be in an inductive definition) - starts with a constructor. - - - .. example:: - - One can define the addition function as : - - .. coqtop:: all - - Fixpoint add (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (add p m) - end. - - The match operator matches a value (here :g:`n`) with the various - constructors of its (inductive) type. The remaining arguments give the - respective values to be returned, as functions of the parameters of the - corresponding constructor. Thus here when :g:`n` equals :g:`O` we return - :g:`m`, and when :g:`n` equals :g:`(S p)` we return :g:`(S (add p m))`. - - The match operator is formally described in - Section :ref:`match-construction`. - The system recognizes that in the inductive call :g:`(add p m)` the first - argument actually decreases because it is a *pattern variable* coming - from :g:`match n with`. - - .. example:: - - The following definition is not correct and generates an error message: - - .. coqtop:: all - - Fail Fixpoint wrongplus (n m:nat) {struct n} : nat := - match m with - | O => n - | S p => S (wrongplus n p) - end. - - because the declared decreasing argument :g:`n` does not actually - decrease in the recursive call. The function computing the addition over - the second argument should rather be written: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct m} : nat := - match m with - | O => n - | S p => S (plus n p) - end. - - .. example:: - - The recursive call may not only be on direct subterms of the recursive - variable :g:`n` but also on a deeper subterm and we can directly write - the function :g:`mod2` which gives the remainder modulo 2 of a natural - number. - - .. coqtop:: all - - Fixpoint mod2 (n:nat) : nat := - match n with - | O => O - | S p => match p with - | O => S O - | S q => mod2 q - end - end. - -.. _example_mutual_fixpoints: - - .. example:: Mutual fixpoints - - The size of trees and forests can be defined the following way: - - .. coqtop:: all - - Fixpoint tree_size (t:tree) : nat := - match t with - | node a f => S (forest_size f) - end - with forest_size (f:forest) : nat := - match f with - | leaf b => 1 - | cons t f' => (tree_size t + forest_size f') - end. - -.. _cofixpoint: - -Definitions of recursive objects in co-inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. cmd:: CoFixpoint @cofix_definition {* with @cofix_definition } - - .. insertprodn cofix_definition cofix_definition - - .. prodn:: - cofix_definition ::= @ident_decl {* @binder } {? : @type } {? := @term } {? @decl_notations } - - This command introduces a method for constructing an infinite object of a - coinductive type. For example, the stream containing all natural numbers can - be introduced applying the following method to the number :g:`O` (see - Section :ref:`coinductive-types` for the definition of :g:`Stream`, :g:`hd` - and :g:`tl`): - - .. coqtop:: all - - CoFixpoint from (n:nat) : Stream := Seq n (from (S n)). - - Unlike recursive definitions, there is no decreasing argument in a - co-recursive definition. To be admissible, a method of construction must - provide at least one extra constructor of the infinite object for each - iteration. A syntactical guard condition is imposed on co-recursive - definitions in order to ensure this: each recursive call in the - definition must be protected by at least one constructor, and only by - constructors. That is the case in the former definition, where the single - recursive call of :g:`from` is guarded by an application of :g:`Seq`. - On the contrary, the following recursive function does not satisfy the - guard condition: - - .. coqtop:: all - - Fail CoFixpoint filter (p:nat -> bool) (s:Stream) : Stream := - if p (hd s) then Seq (hd s) (filter p (tl s)) else filter p (tl s). - - The elimination of co-recursive definition is done lazily, i.e. the - definition is expanded only when it occurs at the head of an application - which is the argument of a case analysis expression. In any other - context, it is considered as a canonical expression which is completely - evaluated. We can test this using the command :cmd:`Eval`, which computes - the normal forms of a term: - - .. coqtop:: all - - Eval compute in (from 0). - Eval compute in (hd (from 0)). - Eval compute in (tl (from 0)). - - As in the :cmd:`Fixpoint` command, the :n:`with` clause allows simultaneously - defining several mutual cofixpoints. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - -.. _Computations: - -Computations ------------- - -.. insertprodn reduce pattern_occ - -.. prodn:: - reduce ::= Eval @red_expr in - red_expr ::= red - | hnf - | simpl {? @delta_flag } {? @ref_or_pattern_occ } - | cbv {? @strategy_flag } - | cbn {? @strategy_flag } - | lazy {? @strategy_flag } - | compute {? @delta_flag } - | vm_compute {? @ref_or_pattern_occ } - | native_compute {? @ref_or_pattern_occ } - | unfold {+, @unfold_occ } - | fold {+ @one_term } - | pattern {+, @pattern_occ } - | @ident - delta_flag ::= {? - } [ {+ @smart_qualid } ] - strategy_flag ::= {+ @red_flags } - | @delta_flag - red_flags ::= beta - | iota - | match - | fix - | cofix - | zeta - | delta {? @delta_flag } - ref_or_pattern_occ ::= @smart_qualid {? at @occs_nums } - | @one_term {? at @occs_nums } - occs_nums ::= {+ {| @num | @ident } } - | - {| @num | @ident } {* @int_or_var } - int_or_var ::= @int - | @ident - unfold_occ ::= @smart_qualid {? at @occs_nums } - pattern_occ ::= @one_term {? at @occs_nums } - -See :ref:`Conversion-rules`. - -.. todo:: Add text here - -.. _Assertions: - -Assertions and proofs ---------------------- - -An assertion states a proposition (or a type) of which the proof (or an -inhabitant of the type) is interactively built using tactics. The interactive -proof mode is described in Chapter :ref:`proofhandling` and the tactics in -Chapter :ref:`Tactics`. The basic assertion command is: - -.. cmd:: @thm_token @ident_decl {* @binder } : @type {* with @ident_decl {* @binder } : @type } - :name: Theorem; Lemma; Fact; Remark; Corollary; Proposition; Property - - .. insertprodn thm_token thm_token - - .. prodn:: - thm_token ::= Theorem - | Lemma - | Fact - | Remark - | Corollary - | Proposition - | Property - - After the statement is asserted, Coq needs a proof. Once a proof of - :n:`@type` under the assumptions represented by :n:`@binder`\s is given and - validated, the proof is generalized into a proof of :n:`forall {* @binder }, @type` and - the theorem is bound to the name :n:`@ident` in the environment. - - Forms using the :n:`with` clause are useful for theorems that are proved by simultaneous induction - over a mutually inductive assumption, or that assert mutually dependent - statements in some mutual co-inductive type. It is equivalent to - :cmd:`Fixpoint` or :cmd:`CoFixpoint` but using tactics to build the proof of - the statements (or the body of the specification, depending on the point of - view). The inductive or co-inductive types on which the induction or - coinduction has to be done is assumed to be non ambiguous and is guessed by - the system. - - Like in a :cmd:`Fixpoint` or :cmd:`CoFixpoint` definition, the induction hypotheses - have to be used on *structurally smaller* arguments (for a :cmd:`Fixpoint`) or - be *guarded by a constructor* (for a :cmd:`CoFixpoint`). The verification that - recursive proof arguments are correct is done only at the time of registering - the lemma in the environment. To know if the use of induction hypotheses is - correct at some time of the interactive development of a proof, use the - command :cmd:`Guarded`. - - .. exn:: The term @term has type @type which should be Set, Prop or Type. - :undocumented: - - .. exn:: @ident already exists. - :name: @ident already exists. (Theorem) - - The name you provided is already defined. You have then to choose - another name. - - .. exn:: Nested proofs are not allowed unless you turn the Nested Proofs Allowed flag on. - - You are asserting a new statement while already being in proof editing mode. - This feature, called nested proofs, is disabled by default. - To activate it, turn the :flag:`Nested Proofs Allowed` flag on. - -Proofs start with the keyword :cmd:`Proof`. Then Coq enters the proof editing mode -until the proof is completed. In proof editing mode, the user primarily enters -tactics, which are described in chapter :ref:`Tactics`. The user may also enter -commands to manage the proof editing mode. They are described in Chapter -:ref:`proofhandling`. - -When the proof is complete, use the :cmd:`Qed` command so the kernel verifies -the proof and adds it to the environment. - -.. note:: - - #. Several statements can be simultaneously asserted provided the - :flag:`Nested Proofs Allowed` flag was turned on. - - #. Not only other assertions but any vernacular command can be given - while in the process of proving a given assertion. In this case, the - command is understood as if it would have been given before the - statements still to be proved. Nonetheless, this practice is discouraged - and may stop working in future versions. - - #. Proofs ended by :cmd:`Qed` are declared opaque. Their content cannot be - unfolded (see :ref:`performingcomputations`), thus - realizing some form of *proof-irrelevance*. To be able to unfold a - proof, the proof should be ended by :cmd:`Defined`. - - #. :cmd:`Proof` is recommended but can currently be omitted. On the opposite - side, :cmd:`Qed` (or :cmd:`Defined`) is mandatory to validate a proof. - - #. One can also use :cmd:`Admitted` in place of :cmd:`Qed` to turn the - current asserted statement into an axiom and exit the proof editing mode. - -.. [1] - Except if the inductive type is empty in which case there is no - equation that can be used to infer the return type. -- cgit v1.2.3 From 4f71e81915a038c8e4d7920822c681c65d500ff2 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 19:55:10 +0200 Subject: Add match to new file on Variants. --- doc/sphinx/language/core/variants.rst | 144 +++++++++++++++++++++ .../language/gallina-specification-language.rst | 144 --------------------- 2 files changed, 144 insertions(+), 144 deletions(-) create mode 100644 doc/sphinx/language/core/variants.rst delete mode 100644 doc/sphinx/language/gallina-specification-language.rst diff --git a/doc/sphinx/language/core/variants.rst b/doc/sphinx/language/core/variants.rst new file mode 100644 index 0000000000..d9e2c07951 --- /dev/null +++ b/doc/sphinx/language/core/variants.rst @@ -0,0 +1,144 @@ +.. index:: match ... with ... + +Definition by cases: match +-------------------------- + +.. insertprodn term_match pattern0 + +.. prodn:: + term_match ::= match {+, @case_item } {? return @term100 } with {? %| } {*| @eqn } end + case_item ::= @term100 {? as @name } {? in @pattern } + eqn ::= {+| {+, @pattern } } => @term + pattern ::= @pattern10 : @term + | @pattern10 + pattern10 ::= @pattern1 as @name + | @pattern1 {* @pattern1 } + | @ @qualid {* @pattern1 } + pattern1 ::= @pattern0 % @scope_key + | @pattern0 + pattern0 ::= @qualid + | %{%| {* @qualid := @pattern } %|%} + | _ + | ( {+| @pattern } ) + | @numeral + | @string + +Objects of inductive types can be destructured by a case-analysis +construction called *pattern matching* expression. A pattern matching +expression is used to analyze the structure of an inductive object and +to apply specific treatments accordingly. + +This paragraph describes the basic form of pattern matching. See +Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description +of the general form. The basic form of pattern matching is characterized +by a single :n:`@case_item` expression, an :n:`@eqn` restricted to a +single :n:`@pattern` and :n:`@pattern` restricted to the form +:n:`@qualid {* @ident}`. + +The expression +:n:`match @term {? return @term100 } with {+| @pattern__i => @term__i } end` denotes a +*pattern matching* over the term :n:`@term` (expected to be +of an inductive type :math:`I`). The :n:`@term__i` +are the *branches* of the pattern matching +expression. Each :n:`@pattern__i` has the form :n:`@qualid @ident` +where :n:`@qualid` must denote a constructor. There should be +exactly one branch for every constructor of :math:`I`. + +The :n:`return @term100` clause gives the type returned by the whole match +expression. There are several cases. In the *non dependent* case, all +branches have the same type, and the :n:`return @term100` specifies that type. +In this case, :n:`return @term100` can usually be omitted as it can be +inferred from the type of the branches [1]_. + +In the *dependent* case, there are three subcases. In the first subcase, +the type in each branch may depend on the exact value being matched in +the branch. In this case, the whole pattern matching itself depends on +the term being matched. This dependency of the term being matched in the +return type is expressed with an :n:`@ident` clause where :n:`@ident` +is dependent in the return type. For instance, in the following example: + +.. coqtop:: in + + Inductive bool : Type := true : bool | false : bool. + Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. + Inductive or (A:Prop) (B:Prop) : Prop := + | or_introl : A -> or A B + | or_intror : B -> or A B. + + Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := + match b as x return or (eq bool x true) (eq bool x false) with + | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) + | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) + end. + +the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`" +and ":g:`or (eq bool false true) (eq bool false false)`" while the whole +pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`", +the identifier :g:`b` being used to represent the dependency. + +.. note:: + + When the term being matched is a variable, the ``as`` clause can be + omitted and the term being matched can serve itself as binding name in + the return type. For instance, the following alternative definition is + accepted and has the same meaning as the previous one. + + .. coqtop:: none + + Reset bool_case. + + .. coqtop:: in + + Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := + match b return or (eq bool b true) (eq bool b false) with + | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) + | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) + end. + +The second subcase is only relevant for annotated inductive types such +as the equality predicate (see Section :ref:`coq-equality`), +the order predicate on natural numbers or the type of lists of a given +length (see Section :ref:`matching-dependent`). In this configuration, the +type of each branch can depend on the type dependencies specific to the +branch and the whole pattern matching expression has a type determined +by the specific dependencies in the type of the term being matched. This +dependency of the return type in the annotations of the inductive type +is expressed with a clause in the form +:n:`in @qualid {+ _ } {+ @pattern }`, where + +- :n:`@qualid` is the inductive type of the term being matched; + +- the holes :n:`_` match the parameters of the inductive type: the + return type is not dependent on them. + +- each :n:`@pattern` matches the annotations of the + inductive type: the return type is dependent on them + +- in the basic case which we describe below, each :n:`@pattern` + is a name :n:`@ident`; see :ref:`match-in-patterns` for the + general case + +For instance, in the following example: + +.. coqtop:: in + + Definition eq_sym (A:Type) (x y:A) (H:eq A x y) : eq A y x := + match H in eq _ _ z return eq A z x with + | eq_refl _ _ => eq_refl A x + end. + +the type of the branch is :g:`eq A x x` because the third argument of +:g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the +type of the whole pattern matching expression has type :g:`eq A y x` because the +third argument of eq is y in the type of H. This dependency of the case analysis +in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the +return type. + +Finally, the third subcase is a combination of the first and second +subcase. In particular, it only applies to pattern matching on terms in +a type with annotations. For this third subcase, both the clauses ``as`` and +``in`` are available. + +There are specific notations for case analysis on types with one or two +constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see +Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst deleted file mode 100644 index d9e2c07951..0000000000 --- a/doc/sphinx/language/gallina-specification-language.rst +++ /dev/null @@ -1,144 +0,0 @@ -.. index:: match ... with ... - -Definition by cases: match --------------------------- - -.. insertprodn term_match pattern0 - -.. prodn:: - term_match ::= match {+, @case_item } {? return @term100 } with {? %| } {*| @eqn } end - case_item ::= @term100 {? as @name } {? in @pattern } - eqn ::= {+| {+, @pattern } } => @term - pattern ::= @pattern10 : @term - | @pattern10 - pattern10 ::= @pattern1 as @name - | @pattern1 {* @pattern1 } - | @ @qualid {* @pattern1 } - pattern1 ::= @pattern0 % @scope_key - | @pattern0 - pattern0 ::= @qualid - | %{%| {* @qualid := @pattern } %|%} - | _ - | ( {+| @pattern } ) - | @numeral - | @string - -Objects of inductive types can be destructured by a case-analysis -construction called *pattern matching* expression. A pattern matching -expression is used to analyze the structure of an inductive object and -to apply specific treatments accordingly. - -This paragraph describes the basic form of pattern matching. See -Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description -of the general form. The basic form of pattern matching is characterized -by a single :n:`@case_item` expression, an :n:`@eqn` restricted to a -single :n:`@pattern` and :n:`@pattern` restricted to the form -:n:`@qualid {* @ident}`. - -The expression -:n:`match @term {? return @term100 } with {+| @pattern__i => @term__i } end` denotes a -*pattern matching* over the term :n:`@term` (expected to be -of an inductive type :math:`I`). The :n:`@term__i` -are the *branches* of the pattern matching -expression. Each :n:`@pattern__i` has the form :n:`@qualid @ident` -where :n:`@qualid` must denote a constructor. There should be -exactly one branch for every constructor of :math:`I`. - -The :n:`return @term100` clause gives the type returned by the whole match -expression. There are several cases. In the *non dependent* case, all -branches have the same type, and the :n:`return @term100` specifies that type. -In this case, :n:`return @term100` can usually be omitted as it can be -inferred from the type of the branches [1]_. - -In the *dependent* case, there are three subcases. In the first subcase, -the type in each branch may depend on the exact value being matched in -the branch. In this case, the whole pattern matching itself depends on -the term being matched. This dependency of the term being matched in the -return type is expressed with an :n:`@ident` clause where :n:`@ident` -is dependent in the return type. For instance, in the following example: - -.. coqtop:: in - - Inductive bool : Type := true : bool | false : bool. - Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. - Inductive or (A:Prop) (B:Prop) : Prop := - | or_introl : A -> or A B - | or_intror : B -> or A B. - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b as x return or (eq bool x true) (eq bool x false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`" -and ":g:`or (eq bool false true) (eq bool false false)`" while the whole -pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`", -the identifier :g:`b` being used to represent the dependency. - -.. note:: - - When the term being matched is a variable, the ``as`` clause can be - omitted and the term being matched can serve itself as binding name in - the return type. For instance, the following alternative definition is - accepted and has the same meaning as the previous one. - - .. coqtop:: none - - Reset bool_case. - - .. coqtop:: in - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b return or (eq bool b true) (eq bool b false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -The second subcase is only relevant for annotated inductive types such -as the equality predicate (see Section :ref:`coq-equality`), -the order predicate on natural numbers or the type of lists of a given -length (see Section :ref:`matching-dependent`). In this configuration, the -type of each branch can depend on the type dependencies specific to the -branch and the whole pattern matching expression has a type determined -by the specific dependencies in the type of the term being matched. This -dependency of the return type in the annotations of the inductive type -is expressed with a clause in the form -:n:`in @qualid {+ _ } {+ @pattern }`, where - -- :n:`@qualid` is the inductive type of the term being matched; - -- the holes :n:`_` match the parameters of the inductive type: the - return type is not dependent on them. - -- each :n:`@pattern` matches the annotations of the - inductive type: the return type is dependent on them - -- in the basic case which we describe below, each :n:`@pattern` - is a name :n:`@ident`; see :ref:`match-in-patterns` for the - general case - -For instance, in the following example: - -.. coqtop:: in - - Definition eq_sym (A:Type) (x y:A) (H:eq A x y) : eq A y x := - match H in eq _ _ z return eq A z x with - | eq_refl _ _ => eq_refl A x - end. - -the type of the branch is :g:`eq A x x` because the third argument of -:g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the -type of the whole pattern matching expression has type :g:`eq A y x` because the -third argument of eq is y in the type of H. This dependency of the case analysis -in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the -return type. - -Finally, the third subcase is a combination of the first and second -subcase. In particular, it only applies to pattern matching on terms in -a type with annotations. For this third subcase, both the clauses ``as`` and -``in`` are available. - -There are specific notations for case analysis on types with one or two -constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see -Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). -- cgit v1.2.3 From d3ad26c8f2b53f3101338f3764ccb54eb0177c3a Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 20:01:56 +0200 Subject: Extract Inductive types from Gallina. --- .../language/gallina-specification-language.rst | 1117 -------------------- 1 file changed, 1117 deletions(-) diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst index 353bed1b3d..b64c0aea95 100644 --- a/doc/sphinx/language/gallina-specification-language.rst +++ b/doc/sphinx/language/gallina-specification-language.rst @@ -1,608 +1,3 @@ -.. _gallinaspecificationlanguage: - ------------------------------------- - The Gallina specification language ------------------------------------- - -This chapter describes Gallina, the specification language of Coq. It allows -developing mathematical theories and to prove specifications of programs. The -theories are built from axioms, hypotheses, parameters, lemmas, theorems and -definitions of constants, functions, predicates and sets. - -.. _term: - -Terms -===== - -.. _gallina-identifiers: - -Qualified identifiers and simple identifiers --------------------------------------------- - -.. insertprodn qualid field_ident - -.. prodn:: - qualid ::= @ident {* @field_ident } - field_ident ::= .@ident - -*Qualified identifiers* (:n:`@qualid`) denote *global constants* -(definitions, lemmas, theorems, remarks or facts), *global variables* -(parameters or axioms), *inductive types* or *constructors of inductive -types*. *Simple identifiers* (or shortly :n:`@ident`) are a syntactic subset -of qualified identifiers. Identifiers may also denote *local variables*, -while qualified identifiers do not. - -Field identifiers, written :n:`@field_ident`, are identifiers prefixed by -`.` (dot) with no blank between the dot and the identifier. - - -Numerals and strings --------------------- - -.. insertprodn primitive_notations primitive_notations - -.. prodn:: - primitive_notations ::= @numeral - | @string - -Numerals and strings have no predefined semantics in the calculus. They are -merely notations that can be bound to objects through the notation mechanism -(see Chapter :ref:`syntax-extensions-and-notation-scopes` for details). -Initially, numerals are bound to Peano’s representation of natural -numbers (see :ref:`datatypes`). - -.. note:: - - Negative integers are not at the same level as :n:`@num`, for this - would make precedence unnatural. - -.. index:: - single: Set (sort) - single: SProp - single: Prop - single: Type - -Sorts ------ - -.. insertprodn sort univ_constraint - -.. prodn:: - sort ::= Set - | Prop - | SProp - | Type - | Type @%{ _ %} - | Type @%{ @universe %} - universe ::= max ( {+, @universe_expr } ) - | @universe_expr - universe_expr ::= @universe_name {? + @num } - universe_name ::= @qualid - | Set - | Prop - univ_annot ::= @%{ {* @universe_level } %} - universe_level ::= Set - | Prop - | Type - | _ - | @qualid - univ_decl ::= @%{ {* @ident } {? + } {? %| {*, @univ_constraint } {? + } } %} - univ_constraint ::= @universe_name {| < | = | <= } @universe_name - -There are four sorts :g:`SProp`, :g:`Prop`, :g:`Set` and :g:`Type`. - -- :g:`SProp` is the universe of *definitionally irrelevant - propositions* (also called *strict propositions*). - -- :g:`Prop` is the universe of *logical propositions*. The logical propositions - themselves are typing the proofs. We denote propositions by :n:`@form`. - This constitutes a semantic subclass of the syntactic class :n:`@term`. - -- :g:`Set` is the universe of *program types* or *specifications*. The - specifications themselves are typing the programs. We denote - specifications by :n:`@specif`. This constitutes a semantic subclass of - the syntactic class :n:`@term`. - -- :g:`Type` is the type of sorts. - -More on sorts can be found in Section :ref:`sorts`. - -.. _binders: - -Binders -------- - -.. insertprodn open_binders binder - -.. prodn:: - open_binders ::= {+ @name } : @term - | {+ @binder } - name ::= _ - | @ident - binder ::= @name - | ( {+ @name } : @type ) - | ( @name {? : @type } := @term ) - | @implicit_binders - | @generalizing_binder - | ( @name : @type %| @term ) - | ' @pattern0 - -Various constructions such as :g:`fun`, :g:`forall`, :g:`fix` and :g:`cofix` -*bind* variables. A binding is represented by an identifier. If the binding -variable is not used in the expression, the identifier can be replaced by the -symbol :g:`_`. When the type of a bound variable cannot be synthesized by the -system, it can be specified with the notation :n:`(@ident : @type)`. There is also -a notation for a sequence of binding variables sharing the same type: -:n:`({+ @ident} : @type)`. A -binder can also be any pattern prefixed by a quote, e.g. :g:`'(x,y)`. - -Some constructions allow the binding of a variable to value. This is -called a “let-binder”. The entry :n:`@binder` of the grammar accepts -either an assumption binder as defined above or a let-binder. The notation in -the latter case is :n:`(@ident := @term)`. In a let-binder, only one -variable can be introduced at the same time. It is also possible to give -the type of the variable as follows: -:n:`(@ident : @type := @term)`. - -Lists of :n:`@binder`\s are allowed. In the case of :g:`fun` and :g:`forall`, -it is intended that at least one binder of the list is an assumption otherwise -fun and forall gets identical. Moreover, parentheses can be omitted in -the case of a single sequence of bindings sharing the same type (e.g.: -:g:`fun (x y z : A) => t` can be shortened in :g:`fun x y z : A => t`). - -.. index:: fun ... => ... - -Abstractions: fun ------------------ - -The expression :n:`fun @ident : @type => @term` defines the -*abstraction* of the variable :n:`@ident`, of type :n:`@type`, over the term -:n:`@term`. It denotes a function of the variable :n:`@ident` that evaluates to -the expression :n:`@term` (e.g. :g:`fun x : A => x` denotes the identity -function on type :g:`A`). The keyword :g:`fun` can be followed by several -binders as given in Section :ref:`binders`. Functions over -several variables are equivalent to an iteration of one-variable -functions. For instance the expression -:n:`fun {+ @ident__i } : @type => @term` -denotes the same function as :n:`{+ fun @ident__i : @type => } @term`. If -a let-binder occurs in -the list of binders, it is expanded to a let-in definition (see -Section :ref:`let-in`). - -.. index:: forall - -Products: forall ----------------- - -.. insertprodn term_forall_or_fun term_forall_or_fun - -.. prodn:: - term_forall_or_fun ::= forall @open_binders , @term - | fun @open_binders => @term - -The expression :n:`forall @ident : @type, @term` denotes the -*product* of the variable :n:`@ident` of type :n:`@type`, over the term :n:`@term`. -As for abstractions, :g:`forall` is followed by a binder list, and products -over several variables are equivalent to an iteration of one-variable -products. Note that :n:`@term` is intended to be a type. - -If the variable :n:`@ident` occurs in :n:`@term`, the product is called -*dependent product*. The intention behind a dependent product -:g:`forall x : A, B` is twofold. It denotes either -the universal quantification of the variable :g:`x` of type :g:`A` -in the proposition :g:`B` or the functional dependent product from -:g:`A` to :g:`B` (a construction usually written -:math:`\Pi_{x:A}.B` in set theory). - -Non dependent product types have a special notation: :g:`A -> B` stands for -:g:`forall _ : A, B`. The *non dependent product* is used both to denote -the propositional implication and function types. - -Applications ------------- - -.. insertprodn term_application arg - -.. prodn:: - term_application ::= @term1 {+ @arg } - | @ @qualid_annotated {+ @term1 } - arg ::= ( @ident := @term ) - | @term1 - -:n:`@term__fun @term` denotes applying the function :n:`@term__fun` to :token:`term`. - -:n:`@term__fun {+ @term__i }` denotes applying -:n:`@term__fun` to the arguments :n:`@term__i`. It is -equivalent to :n:`( … ( @term__fun @term__1 ) … ) @term__n`: -associativity is to the left. - -The notation :n:`(@ident := @term)` for arguments is used for making -explicit the value of implicit arguments (see -Section :ref:`explicit-applications`). - -.. index:: - single: ... : ... (type cast) - single: ... <: ... - single: ... <<: ... - -Type cast ---------- - -.. insertprodn term_cast term_cast - -.. prodn:: - term_cast ::= @term10 <: @term - | @term10 <<: @term - | @term10 : @term - | @term10 :> - -The expression :n:`@term : @type` is a type cast expression. It enforces -the type of :n:`@term` to be :n:`@type`. - -:n:`@term <: @type` locally sets up the virtual machine for checking that -:n:`@term` has type :n:`@type`. - -:n:`@term <<: @type` uses native compilation for checking that :n:`@term` -has type :n:`@type`. - -.. index:: _ - -Inferable subterms ------------------- - -Expressions often contain redundant pieces of information. Subterms that can be -automatically inferred by Coq can be replaced by the symbol ``_`` and Coq will -guess the missing piece of information. - -.. index:: let ... := ... (term) - -.. _let-in: - -Let-in definitions ------------------- - -.. insertprodn term_let term_let - -.. prodn:: - term_let ::= let @name {? : @type } := @term in @term - | let @name {+ @binder } {? : @type } := @term in @term - | let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term - | let ' @pattern := @term {? return @term100 } in @term - | let ' @pattern in @pattern := @term return @term100 in @term - -:n:`let @ident := @term in @term’` -denotes the local binding of :n:`@term` to the variable -:n:`@ident` in :n:`@term`’. There is a syntactic sugar for let-in -definition of functions: :n:`let @ident {+ @binder} := @term in @term’` -stands for :n:`let @ident := fun {+ @binder} => @term in @term’`. - -.. index:: match ... with ... - -Definition by cases: match --------------------------- - -.. insertprodn term_match pattern0 - -.. prodn:: - term_match ::= match {+, @case_item } {? return @term100 } with {? %| } {*| @eqn } end - case_item ::= @term100 {? as @name } {? in @pattern } - eqn ::= {+| {+, @pattern } } => @term - pattern ::= @pattern10 : @term - | @pattern10 - pattern10 ::= @pattern1 as @name - | @pattern1 {* @pattern1 } - | @ @qualid {* @pattern1 } - pattern1 ::= @pattern0 % @scope_key - | @pattern0 - pattern0 ::= @qualid - | %{%| {* @qualid := @pattern } %|%} - | _ - | ( {+| @pattern } ) - | @numeral - | @string - -Objects of inductive types can be destructured by a case-analysis -construction called *pattern matching* expression. A pattern matching -expression is used to analyze the structure of an inductive object and -to apply specific treatments accordingly. - -This paragraph describes the basic form of pattern matching. See -Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description -of the general form. The basic form of pattern matching is characterized -by a single :n:`@case_item` expression, an :n:`@eqn` restricted to a -single :n:`@pattern` and :n:`@pattern` restricted to the form -:n:`@qualid {* @ident}`. - -The expression -:n:`match @term {? return @term100 } with {+| @pattern__i => @term__i } end` denotes a -*pattern matching* over the term :n:`@term` (expected to be -of an inductive type :math:`I`). The :n:`@term__i` -are the *branches* of the pattern matching -expression. Each :n:`@pattern__i` has the form :n:`@qualid @ident` -where :n:`@qualid` must denote a constructor. There should be -exactly one branch for every constructor of :math:`I`. - -The :n:`return @term100` clause gives the type returned by the whole match -expression. There are several cases. In the *non dependent* case, all -branches have the same type, and the :n:`return @term100` specifies that type. -In this case, :n:`return @term100` can usually be omitted as it can be -inferred from the type of the branches [1]_. - -In the *dependent* case, there are three subcases. In the first subcase, -the type in each branch may depend on the exact value being matched in -the branch. In this case, the whole pattern matching itself depends on -the term being matched. This dependency of the term being matched in the -return type is expressed with an :n:`@ident` clause where :n:`@ident` -is dependent in the return type. For instance, in the following example: - -.. coqtop:: in - - Inductive bool : Type := true : bool | false : bool. - Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. - Inductive or (A:Prop) (B:Prop) : Prop := - | or_introl : A -> or A B - | or_intror : B -> or A B. - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b as x return or (eq bool x true) (eq bool x false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`" -and ":g:`or (eq bool false true) (eq bool false false)`" while the whole -pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`", -the identifier :g:`b` being used to represent the dependency. - -.. note:: - - When the term being matched is a variable, the ``as`` clause can be - omitted and the term being matched can serve itself as binding name in - the return type. For instance, the following alternative definition is - accepted and has the same meaning as the previous one. - - .. coqtop:: none - - Reset bool_case. - - .. coqtop:: in - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b return or (eq bool b true) (eq bool b false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -The second subcase is only relevant for annotated inductive types such -as the equality predicate (see Section :ref:`coq-equality`), -the order predicate on natural numbers or the type of lists of a given -length (see Section :ref:`matching-dependent`). In this configuration, the -type of each branch can depend on the type dependencies specific to the -branch and the whole pattern matching expression has a type determined -by the specific dependencies in the type of the term being matched. This -dependency of the return type in the annotations of the inductive type -is expressed with a clause in the form -:n:`in @qualid {+ _ } {+ @pattern }`, where - -- :n:`@qualid` is the inductive type of the term being matched; - -- the holes :n:`_` match the parameters of the inductive type: the - return type is not dependent on them. - -- each :n:`@pattern` matches the annotations of the - inductive type: the return type is dependent on them - -- in the basic case which we describe below, each :n:`@pattern` - is a name :n:`@ident`; see :ref:`match-in-patterns` for the - general case - -For instance, in the following example: - -.. coqtop:: in - - Definition eq_sym (A:Type) (x y:A) (H:eq A x y) : eq A y x := - match H in eq _ _ z return eq A z x with - | eq_refl _ _ => eq_refl A x - end. - -the type of the branch is :g:`eq A x x` because the third argument of -:g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the -type of the whole pattern matching expression has type :g:`eq A y x` because the -third argument of eq is y in the type of H. This dependency of the case analysis -in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the -return type. - -Finally, the third subcase is a combination of the first and second -subcase. In particular, it only applies to pattern matching on terms in -a type with annotations. For this third subcase, both the clauses ``as`` and -``in`` are available. - -There are specific notations for case analysis on types with one or two -constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see -Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). - -.. index:: - single: fix - single: cofix - -Recursive and co-recursive functions: fix and cofix ---------------------------------------------------- - -.. insertprodn term_fix fixannot - -.. prodn:: - term_fix ::= let fix @fix_body in @term - | fix @fix_body {? {+ with @fix_body } for @ident } - fix_body ::= @ident {* @binder } {? @fixannot } {? : @type } := @term - fixannot ::= %{ struct @ident %} - | %{ wf @one_term @ident %} - | %{ measure @one_term {? @ident } {? @one_term } %} - - -The expression ":n:`fix @ident__1 @binder__1 : @type__1 := @term__1 with … with @ident__n @binder__n : @type__n := @term__n for @ident__i`" denotes the -:math:`i`-th component of a block of functions defined by mutual structural -recursion. It is the local counterpart of the :cmd:`Fixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -The association of a single fixpoint and a local definition have a special -syntax: :n:`let fix @ident {* @binder } := @term in` stands for -:n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for co-fixpoints. - -Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` -only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in -commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. - -.. insertprodn term_cofix cofix_body - -.. prodn:: - term_cofix ::= let cofix @cofix_body in @term - | cofix @cofix_body {? {+ with @cofix_body } for @ident } - cofix_body ::= @ident {* @binder } {? : @type } := @term - -The expression -":n:`cofix @ident__1 @binder__1 : @type__1 with … with @ident__n @binder__n : @type__n for @ident__i`" -denotes the :math:`i`-th component of a block of terms defined by a mutual guarded -co-recursion. It is the local counterpart of the :cmd:`CoFixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -.. _vernacular: - -The Vernacular -============== - -.. _gallina-assumptions: - -Assumptions ------------ - -Assumptions extend the environment with axioms, parameters, hypotheses -or variables. An assumption binds an :n:`@ident` to a :n:`@type`. It is accepted -by Coq if and only if this :n:`@type` is a correct type in the environment -preexisting the declaration and if :n:`@ident` was not previously defined in -the same module. This :n:`@type` is considered to be the type (or -specification, or statement) assumed by :n:`@ident` and we say that :n:`@ident` -has type :n:`@type`. - -.. _Axiom: - -.. cmd:: @assumption_token {? Inline {? ( @num ) } } {| {+ ( @assumpt ) } | @assumpt } - :name: Axiom; Axioms; Conjecture; Conjectures; Hypothesis; Hypotheses; Parameter; Parameters; Variable; Variables - - .. insertprodn assumption_token of_type - - .. prodn:: - assumption_token ::= {| Axiom | Axioms } - | {| Conjecture | Conjectures } - | {| Parameter | Parameters } - | {| Hypothesis | Hypotheses } - | {| Variable | Variables } - assumpt ::= {+ @ident_decl } @of_type - ident_decl ::= @ident {? @univ_decl } - of_type ::= {| : | :> | :>> } @type - - These commands bind one or more :n:`@ident`\(s) to specified :n:`@type`\(s) as their specifications in - the global context. The fact asserted by the :n:`@type` (or, equivalently, the existence - of an object of this type) is accepted as a postulate. - - :cmd:`Axiom`, :cmd:`Conjecture`, :cmd:`Parameter` and their plural forms - are equivalent. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident`\s accessible by :cmd:`Import` and its variants - only through their fully qualified names. - - Similarly, :cmd:`Hypothesis`, :cmd:`Variable` and their plural forms are equivalent. Outside - of a section, these are equivalent to :n:`Local Parameter`. Inside a section, the - :n:`@ident`\s defined are only accessible within the section. When the current section - is closed, the :n:`@ident`\(s) become undefined and every object depending on them will be explicitly - parameterized (i.e., the variables are *discharged*). See Section :ref:`section-mechanism`. - - The :n:`Inline` clause is only relevant inside functors. See :cmd:`Module`. - -.. example:: Simple assumptions - - .. coqtop:: reset in - - Parameter X Y : Set. - Parameter (R : X -> Y -> Prop) (S : Y -> X -> Prop). - Axiom R_S_inv : forall x y, R x y <-> S y x. - -.. exn:: @ident already exists. - :name: @ident already exists. (Axiom) - :undocumented: - -.. warn:: @ident is declared as a local axiom - - Warning generated when using :cmd:`Variable` or its equivalent - instead of :n:`Local Parameter` or its equivalent. - -.. note:: - We advise using the commands :cmd:`Axiom`, :cmd:`Conjecture` and - :cmd:`Hypothesis` (and their plural forms) for logical postulates (i.e. when - the assertion :n:`@type` is of sort :g:`Prop`), and to use the commands - :cmd:`Parameter` and :cmd:`Variable` (and their plural forms) in other cases - (corresponding to the declaration of an abstract object of the given type). - -.. _gallina-definitions: - -Definitions ------------ - -Definitions extend the environment with associations of names to terms. -A definition can be seen as a way to give a meaning to a name or as a -way to abbreviate a term. In any case, the name can later be replaced at -any time by its definition. - -The operation of unfolding a name into its definition is called -:math:`\delta`-conversion (see Section :ref:`delta-reduction`). A -definition is accepted by the system if and only if the defined term is -well-typed in the current context of the definition and if the name is -not already used. The name defined by the definition is called a -*constant* and the term it refers to is its *body*. A definition has a -type which is the type of its body. - -A formal presentation of constants and environments is given in -Section :ref:`typing-rules`. - -.. cmd:: {| Definition | Example } @ident_decl @def_body - :name: Definition; Example - - .. insertprodn def_body def_body - - .. prodn:: - def_body ::= {* @binder } {? : @type } := {? @reduce } @term - | {* @binder } : @type - - These commands bind :n:`@term` to the name :n:`@ident` in the environment, - provided that :n:`@term` is well-typed. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident` accessible by :cmd:`Import` and its variants - only through their fully qualified names. - If :n:`@reduce` is present then :n:`@ident` is bound to the result of the specified - computation on :n:`@term`. - - These commands also support the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`program` and - :attr:`canonical` attributes. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - The form :n:`Definition @ident : @type := @term` checks that the type of :n:`@term` - is definitionally equal to :n:`@type`, and registers :n:`@ident` as being of type - :n:`@type`, and bound to value :n:`@term`. - - The form :n:`Definition @ident {* @binder } : @type := @term` is equivalent to - :n:`Definition @ident : forall {* @binder }, @type := fun {* @binder } => @term`. - - .. seealso:: :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`. - - .. exn:: @ident already exists. - :name: @ident already exists. (Definition) - :undocumented: - - .. exn:: The term @term has type @type while it is expected to have type @type'. - :undocumented: - .. _gallina-inductive-definitions: Inductive types @@ -935,518 +330,6 @@ Mutually defined inductive types A generic command :cmd:`Scheme` is useful to build automatically various mutual induction principles. -Private (matching) inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attr:: private(matching) - - This attribute can be used to forbid the use of the :g:`match` - construct on objects of this inductive type outside of the module - where it is defined. There is also a legacy syntax using the - ``Private`` prefix (cf. :n:`@legacy_attr`). - - The main use case of private (matching) inductive types is to emulate - quotient types / higher-order inductive types in projects such as - the `HoTT library `_. - -.. example:: - - .. coqtop:: all - - Module Foo. - #[ private(matching) ] Inductive my_nat := my_O : my_nat | my_S : my_nat -> my_nat. - Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - End Foo. - Import Foo. - Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - -Variants -~~~~~~~~ - -.. cmd:: Variant @variant_definition {* with @variant_definition } - - .. insertprodn variant_definition variant_definition - - .. prodn:: - variant_definition ::= @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? %| } {+| @constructor } {? @decl_notations } - - The :cmd:`Variant` command is similar to the :cmd:`Inductive` command, except - that it disallows recursive definition of types (for instance, lists cannot - be defined using :cmd:`Variant`). No induction scheme is generated for - this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - .. exn:: The @num th argument of @ident must be @ident in @type. - :undocumented: - -.. _coinductive-types: - -Co-inductive types ------------------- - -The objects of an inductive type are well-founded with respect to the -constructors of the type. In other words, such objects contain only a -*finite* number of constructors. Co-inductive types arise from relaxing -this condition, and admitting types whose objects contain an infinity of -constructors. Infinite objects are introduced by a non-ending (but -effective) process of construction, defined in terms of the constructors -of the type. - -.. cmd:: CoInductive @inductive_definition {* with @inductive_definition } - - This command introduces a co-inductive type. - The syntax of the command is the same as the command :cmd:`Inductive`. - No principle of induction is derived from the definition of a co-inductive - type, since such principles only make sense for inductive types. - For co-inductive types, the only elimination principle is case analysis. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - -.. example:: - - The type of infinite sequences of natural numbers, usually called streams, - is an example of a co-inductive type. - - .. coqtop:: in - - CoInductive Stream : Set := Seq : nat -> Stream -> Stream. - - The usual destructors on streams :g:`hd:Stream->nat` and :g:`tl:Str->Str` - can be defined as follows: - - .. coqtop:: in - - Definition hd (x:Stream) := let (a,s) := x in a. - Definition tl (x:Stream) := let (a,s) := x in s. - -Definitions of co-inductive predicates and blocks of mutually -co-inductive definitions are also allowed. - -.. example:: - - The extensional equality on streams is an example of a co-inductive type: - - .. coqtop:: in - - CoInductive EqSt : Stream -> Stream -> Prop := - eqst : forall s1 s2:Stream, - hd s1 = hd s2 -> EqSt (tl s1) (tl s2) -> EqSt s1 s2. - - In order to prove the extensional equality of two streams :g:`s1` and :g:`s2` - we have to construct an infinite proof of equality, that is, an infinite - object of type :g:`(EqSt s1 s2)`. We will see how to introduce infinite - objects in Section :ref:`cofixpoint`. - -Caveat -~~~~~~ - -The ability to define co-inductive types by constructors, hereafter called -*positive co-inductive types*, is known to break subject reduction. The story is -a bit long: this is due to dependent pattern-matching which implies -propositional η-equality, which itself would require full η-conversion for -subject reduction to hold, but full η-conversion is not acceptable as it would -make type checking undecidable. - -Since the introduction of primitive records in Coq 8.5, an alternative -presentation is available, called *negative co-inductive types*. This consists -in defining a co-inductive type as a primitive record type through its -projections. Such a technique is akin to the *co-pattern* style that can be -found in e.g. Agda, and preserves subject reduction. - -The above example can be rewritten in the following way. - -.. coqtop:: none - - Reset Stream. - -.. coqtop:: all - - Set Primitive Projections. - CoInductive Stream : Set := Seq { hd : nat; tl : Stream }. - CoInductive EqSt (s1 s2: Stream) : Prop := eqst { - eqst_hd : hd s1 = hd s2; - eqst_tl : EqSt (tl s1) (tl s2); - }. - -Some properties that hold over positive streams are lost when going to the -negative presentation, typically when they imply equality over streams. -For instance, propositional η-equality is lost when going to the negative -presentation. It is nonetheless logically consistent to recover it through an -axiom. - -.. coqtop:: all - - Axiom Stream_eta : forall s: Stream, s = Seq (hd s) (tl s). - -More generally, as in the case of positive coinductive types, it is consistent -to further identify extensional equality of coinductive types with propositional -equality: - -.. coqtop:: all - - Axiom Stream_ext : forall (s1 s2: Stream), EqSt s1 s2 -> s1 = s2. - -As of Coq 8.9, it is now advised to use negative co-inductive types rather than -their positive counterparts. - -.. seealso:: - :ref:`primitive_projections` for more information about negative - records and primitive projections. - - -Definition of recursive functions ---------------------------------- - -Definition of functions by recursion over inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This section describes the primitive form of definition by recursion over -inductive objects. See the :cmd:`Function` command for more advanced -constructions. - -.. _Fixpoint: - -.. cmd:: Fixpoint @fix_definition {* with @fix_definition } - - .. insertprodn fix_definition fix_definition - - .. prodn:: - fix_definition ::= @ident_decl {* @binder } {? @fixannot } {? : @type } {? := @term } {? @decl_notations } - - This command allows defining functions by pattern matching over inductive - objects using a fixed point construction. The meaning of this declaration is - to define :n:`@ident` as a recursive function with arguments specified by - the :n:`@binder`\s such that :n:`@ident` applied to arguments - corresponding to these :n:`@binder`\s has type :n:`@type`, and is - equivalent to the expression :n:`@term`. The type of :n:`@ident` is - consequently :n:`forall {* @binder }, @type` and its value is equivalent - to :n:`fun {* @binder } => @term`. - - To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical - constraints on a special argument called the decreasing argument. They - are needed to ensure that the :cmd:`Fixpoint` definition always terminates. - The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to - let the user tell the system which argument decreases along the recursive calls. - - The :n:`{struct @ident}` annotation may be left implicit, in which case the - system successively tries arguments from left to right until it finds one - that satisfies the decreasing condition. - - :cmd:`Fixpoint` without the :attr:`program` attribute does not support the - :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. - - The :n:`with` clause allows simultaneously defining several mutual fixpoints. - It is especially useful when defining functions over mutually defined - inductive types. Example: :ref:`Mutual Fixpoints`. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - .. note:: - - + Some fixpoints may have several arguments that fit as decreasing - arguments, and this choice influences the reduction of the fixpoint. - Hence an explicit annotation must be used if the leftmost decreasing - argument is not the desired one. Writing explicit annotations can also - speed up type checking of large mutual fixpoints. - - + In order to keep the strong normalization property, the fixed point - reduction will only be performed when the argument in position of the - decreasing argument (which type should be in an inductive definition) - starts with a constructor. - - - .. example:: - - One can define the addition function as : - - .. coqtop:: all - - Fixpoint add (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (add p m) - end. - - The match operator matches a value (here :g:`n`) with the various - constructors of its (inductive) type. The remaining arguments give the - respective values to be returned, as functions of the parameters of the - corresponding constructor. Thus here when :g:`n` equals :g:`O` we return - :g:`m`, and when :g:`n` equals :g:`(S p)` we return :g:`(S (add p m))`. - - The match operator is formally described in - Section :ref:`match-construction`. - The system recognizes that in the inductive call :g:`(add p m)` the first - argument actually decreases because it is a *pattern variable* coming - from :g:`match n with`. - - .. example:: - - The following definition is not correct and generates an error message: - - .. coqtop:: all - - Fail Fixpoint wrongplus (n m:nat) {struct n} : nat := - match m with - | O => n - | S p => S (wrongplus n p) - end. - - because the declared decreasing argument :g:`n` does not actually - decrease in the recursive call. The function computing the addition over - the second argument should rather be written: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct m} : nat := - match m with - | O => n - | S p => S (plus n p) - end. - - .. example:: - - The recursive call may not only be on direct subterms of the recursive - variable :g:`n` but also on a deeper subterm and we can directly write - the function :g:`mod2` which gives the remainder modulo 2 of a natural - number. - - .. coqtop:: all - - Fixpoint mod2 (n:nat) : nat := - match n with - | O => O - | S p => match p with - | O => S O - | S q => mod2 q - end - end. - -.. _example_mutual_fixpoints: - - .. example:: Mutual fixpoints - - The size of trees and forests can be defined the following way: - - .. coqtop:: all - - Fixpoint tree_size (t:tree) : nat := - match t with - | node a f => S (forest_size f) - end - with forest_size (f:forest) : nat := - match f with - | leaf b => 1 - | cons t f' => (tree_size t + forest_size f') - end. - -.. _cofixpoint: - -Definitions of recursive objects in co-inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. cmd:: CoFixpoint @cofix_definition {* with @cofix_definition } - - .. insertprodn cofix_definition cofix_definition - - .. prodn:: - cofix_definition ::= @ident_decl {* @binder } {? : @type } {? := @term } {? @decl_notations } - - This command introduces a method for constructing an infinite object of a - coinductive type. For example, the stream containing all natural numbers can - be introduced applying the following method to the number :g:`O` (see - Section :ref:`coinductive-types` for the definition of :g:`Stream`, :g:`hd` - and :g:`tl`): - - .. coqtop:: all - - CoFixpoint from (n:nat) : Stream := Seq n (from (S n)). - - Unlike recursive definitions, there is no decreasing argument in a - co-recursive definition. To be admissible, a method of construction must - provide at least one extra constructor of the infinite object for each - iteration. A syntactical guard condition is imposed on co-recursive - definitions in order to ensure this: each recursive call in the - definition must be protected by at least one constructor, and only by - constructors. That is the case in the former definition, where the single - recursive call of :g:`from` is guarded by an application of :g:`Seq`. - On the contrary, the following recursive function does not satisfy the - guard condition: - - .. coqtop:: all - - Fail CoFixpoint filter (p:nat -> bool) (s:Stream) : Stream := - if p (hd s) then Seq (hd s) (filter p (tl s)) else filter p (tl s). - - The elimination of co-recursive definition is done lazily, i.e. the - definition is expanded only when it occurs at the head of an application - which is the argument of a case analysis expression. In any other - context, it is considered as a canonical expression which is completely - evaluated. We can test this using the command :cmd:`Eval`, which computes - the normal forms of a term: - - .. coqtop:: all - - Eval compute in (from 0). - Eval compute in (hd (from 0)). - Eval compute in (tl (from 0)). - - As in the :cmd:`Fixpoint` command, the :n:`with` clause allows simultaneously - defining several mutual cofixpoints. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - -.. _Computations: - -Computations ------------- - -.. insertprodn reduce pattern_occ - -.. prodn:: - reduce ::= Eval @red_expr in - red_expr ::= red - | hnf - | simpl {? @delta_flag } {? @ref_or_pattern_occ } - | cbv {? @strategy_flag } - | cbn {? @strategy_flag } - | lazy {? @strategy_flag } - | compute {? @delta_flag } - | vm_compute {? @ref_or_pattern_occ } - | native_compute {? @ref_or_pattern_occ } - | unfold {+, @unfold_occ } - | fold {+ @one_term } - | pattern {+, @pattern_occ } - | @ident - delta_flag ::= {? - } [ {+ @smart_qualid } ] - strategy_flag ::= {+ @red_flags } - | @delta_flag - red_flags ::= beta - | iota - | match - | fix - | cofix - | zeta - | delta {? @delta_flag } - ref_or_pattern_occ ::= @smart_qualid {? at @occs_nums } - | @one_term {? at @occs_nums } - occs_nums ::= {+ {| @num | @ident } } - | - {| @num | @ident } {* @int_or_var } - int_or_var ::= @int - | @ident - unfold_occ ::= @smart_qualid {? at @occs_nums } - pattern_occ ::= @one_term {? at @occs_nums } - -See :ref:`Conversion-rules`. - -.. todo:: Add text here - -.. _Assertions: - -Assertions and proofs ---------------------- - -An assertion states a proposition (or a type) of which the proof (or an -inhabitant of the type) is interactively built using tactics. The interactive -proof mode is described in Chapter :ref:`proofhandling` and the tactics in -Chapter :ref:`Tactics`. The basic assertion command is: - -.. cmd:: @thm_token @ident_decl {* @binder } : @type {* with @ident_decl {* @binder } : @type } - :name: Theorem; Lemma; Fact; Remark; Corollary; Proposition; Property - - .. insertprodn thm_token thm_token - - .. prodn:: - thm_token ::= Theorem - | Lemma - | Fact - | Remark - | Corollary - | Proposition - | Property - - After the statement is asserted, Coq needs a proof. Once a proof of - :n:`@type` under the assumptions represented by :n:`@binder`\s is given and - validated, the proof is generalized into a proof of :n:`forall {* @binder }, @type` and - the theorem is bound to the name :n:`@ident` in the environment. - - Forms using the :n:`with` clause are useful for theorems that are proved by simultaneous induction - over a mutually inductive assumption, or that assert mutually dependent - statements in some mutual co-inductive type. It is equivalent to - :cmd:`Fixpoint` or :cmd:`CoFixpoint` but using tactics to build the proof of - the statements (or the body of the specification, depending on the point of - view). The inductive or co-inductive types on which the induction or - coinduction has to be done is assumed to be non ambiguous and is guessed by - the system. - - Like in a :cmd:`Fixpoint` or :cmd:`CoFixpoint` definition, the induction hypotheses - have to be used on *structurally smaller* arguments (for a :cmd:`Fixpoint`) or - be *guarded by a constructor* (for a :cmd:`CoFixpoint`). The verification that - recursive proof arguments are correct is done only at the time of registering - the lemma in the environment. To know if the use of induction hypotheses is - correct at some time of the interactive development of a proof, use the - command :cmd:`Guarded`. - - .. exn:: The term @term has type @type which should be Set, Prop or Type. - :undocumented: - - .. exn:: @ident already exists. - :name: @ident already exists. (Theorem) - - The name you provided is already defined. You have then to choose - another name. - - .. exn:: Nested proofs are not allowed unless you turn the Nested Proofs Allowed flag on. - - You are asserting a new statement while already being in proof editing mode. - This feature, called nested proofs, is disabled by default. - To activate it, turn the :flag:`Nested Proofs Allowed` flag on. - -Proofs start with the keyword :cmd:`Proof`. Then Coq enters the proof editing mode -until the proof is completed. In proof editing mode, the user primarily enters -tactics, which are described in chapter :ref:`Tactics`. The user may also enter -commands to manage the proof editing mode. They are described in Chapter -:ref:`proofhandling`. - -When the proof is complete, use the :cmd:`Qed` command so the kernel verifies -the proof and adds it to the environment. - -.. note:: - - #. Several statements can be simultaneously asserted provided the - :flag:`Nested Proofs Allowed` flag was turned on. - - #. Not only other assertions but any vernacular command can be given - while in the process of proving a given assertion. In this case, the - command is understood as if it would have been given before the - statements still to be proved. Nonetheless, this practice is discouraged - and may stop working in future versions. - - #. Proofs ended by :cmd:`Qed` are declared opaque. Their content cannot be - unfolded (see :ref:`performingcomputations`), thus - realizing some form of *proof-irrelevance*. To be able to unfold a - proof, the proof should be ended by :cmd:`Defined`. - - #. :cmd:`Proof` is recommended but can currently be omitted. On the opposite - side, :cmd:`Qed` (or :cmd:`Defined`) is mandatory to validate a proof. - - #. One can also use :cmd:`Admitted` in place of :cmd:`Qed` to turn the - current asserted statement into an axiom and exit the proof editing mode. - .. [1] Except if the inductive type is empty in which case there is no equation that can be used to infer the return type. -- cgit v1.2.3 From a403808cc4151242ec64d63df63b27128c539191 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 20:02:37 +0200 Subject: Create new file on Inductive types. --- doc/sphinx/language/core/inductive.rst | 335 +++++++++++++++++++++ .../language/gallina-specification-language.rst | 335 --------------------- 2 files changed, 335 insertions(+), 335 deletions(-) create mode 100644 doc/sphinx/language/core/inductive.rst delete mode 100644 doc/sphinx/language/gallina-specification-language.rst diff --git a/doc/sphinx/language/core/inductive.rst b/doc/sphinx/language/core/inductive.rst new file mode 100644 index 0000000000..b64c0aea95 --- /dev/null +++ b/doc/sphinx/language/core/inductive.rst @@ -0,0 +1,335 @@ +.. _gallina-inductive-definitions: + +Inductive types +--------------- + +.. cmd:: Inductive @inductive_definition {* with @inductive_definition } + + .. insertprodn inductive_definition constructor + + .. prodn:: + inductive_definition ::= {? > } @ident_decl {* @binder } {? %| {* @binder } } {? : @type } {? := {? @constructors_or_record } } {? @decl_notations } + constructors_or_record ::= {? %| } {+| @constructor } + | {? @ident } %{ {*; @record_field } %} + constructor ::= @ident {* @binder } {? @of_type } + + This command defines one or more + inductive types and its constructors. Coq generates destructors + depending on the universe that the inductive type belongs to. + + The destructors are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, + :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``, which + respectively correspond to elimination principles on :g:`Type`, :g:`Prop`, + :g:`Set` and :g:`SProp`. The type of the destructors + expresses structural induction/recursion principles over objects of + type :n:`@ident`. The constant :n:`@ident`\ ``_ind`` is always + generated, whereas :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_rect`` + may be impossible to derive (for example, when :n:`@ident` is a + proposition). + + This command supports the :attr:`universes(polymorphic)`, + :attr:`universes(monomorphic)`, :attr:`universes(template)`, + :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, + :attr:`universes(noncumulative)` and :attr:`private(matching)` + attributes. + + Mutually inductive types can be defined by including multiple :n:`@inductive_definition`\s. + The :n:`@ident`\s are simultaneously added to the environment before the types of constructors are checked. + Each :n:`@ident` can be used independently thereafter. + See :ref:`mutually_inductive_types`. + + If the entire inductive definition is parameterized with :n:`@binder`\s, the parameters correspond + to a local context in which the entire set of inductive declarations is interpreted. + For this reason, the parameters must be strictly the same for each inductive type. + See :ref:`parametrized-inductive-types`. + + Constructor :n:`@ident`\s can come with :n:`@binder`\s, in which case + the actual type of the constructor is :n:`forall {* @binder }, @type`. + + .. exn:: Non strictly positive occurrence of @ident in @type. + + The types of the constructors have to satisfy a *positivity condition* + (see Section :ref:`positivity`). This condition ensures the soundness of + the inductive definition. The positivity checking can be disabled using + the :flag:`Positivity Checking` flag (see :ref:`controlling-typing-flags`). + + .. exn:: The conclusion of @type is not valid; it must be built from @ident. + + The conclusion of the type of the constructors must be the inductive type + :n:`@ident` being defined (or :n:`@ident` applied to arguments in + the case of annotated inductive types — cf. next section). + +The following subsections show examples of simple inductive types, +simple annotated inductive types, simple parametric inductive types, +mutually inductive types and private (matching) inductive types. + +.. _simple-inductive-types: + +Simple inductive types +~~~~~~~~~~~~~~~~~~~~~~ + +A simple inductive type belongs to a universe that is a simple :n:`@sort`. + +.. example:: + + The set of natural numbers is defined as: + + .. coqtop:: reset all + + Inductive nat : Set := + | O : nat + | S : nat -> nat. + + The type nat is defined as the least :g:`Set` containing :g:`O` and closed by + the :g:`S` constructor. The names :g:`nat`, :g:`O` and :g:`S` are added to the + environment. + + This definition generates four elimination principles: + :g:`nat_rect`, :g:`nat_ind`, :g:`nat_rec` and :g:`nat_sind`. The type of :g:`nat_ind` is: + + .. coqtop:: all + + Check nat_ind. + + This is the well known structural induction principle over natural + numbers, i.e. the second-order form of Peano’s induction principle. It + allows proving universal properties of natural numbers (:g:`forall + n:nat, P n`) by induction on :g:`n`. + + The types of :g:`nat_rect`, :g:`nat_rec` and :g:`nat_sind` are similar, except that they + apply to, respectively, :g:`(P:nat->Type)`, :g:`(P:nat->Set)` and :g:`(P:nat->SProp)`. They correspond to + primitive induction principles (allowing dependent types) respectively + over sorts ```Type``, ``Set`` and ``SProp``. + +In the case where inductive types don't have annotations (the next section +gives an example of annotations), a constructor can be defined +by giving the type of its arguments alone. + +.. example:: + + .. coqtop:: reset none + + Reset nat. + + .. coqtop:: in + + Inductive nat : Set := O | S (_:nat). + +Simple annotated inductive types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In annotated inductive types, the universe where the inductive type +is defined is no longer a simple :n:`@sort`, but what is called an arity, +which is a type whose conclusion is a :n:`@sort`. + +.. example:: + + As an example of annotated inductive types, let us define the + :g:`even` predicate: + + .. coqtop:: all + + Inductive even : nat -> Prop := + | even_0 : even O + | even_SS : forall n:nat, even n -> even (S (S n)). + + The type :g:`nat->Prop` means that :g:`even` is a unary predicate (inductively + defined) over natural numbers. The type of its two constructors are the + defining clauses of the predicate :g:`even`. The type of :g:`even_ind` is: + + .. coqtop:: all + + Check even_ind. + + From a mathematical point of view, this asserts that the natural numbers satisfying + the predicate :g:`even` are exactly in the smallest set of naturals satisfying the + clauses :g:`even_0` or :g:`even_SS`. This is why, when we want to prove any + predicate :g:`P` over elements of :g:`even`, it is enough to prove it for :g:`O` + and to prove that if any natural number :g:`n` satisfies :g:`P` its double + successor :g:`(S (S n))` satisfies also :g:`P`. This is analogous to the + structural induction principle we got for :g:`nat`. + +.. _parametrized-inductive-types: + +Parameterized inductive types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In the previous example, each constructor introduces a different +instance of the predicate :g:`even`. In some cases, all the constructors +introduce the same generic instance of the inductive definition, in +which case, instead of an annotation, we use a context of parameters +which are :n:`@binder`\s shared by all the constructors of the definition. + +Parameters differ from inductive type annotations in that the +conclusion of each type of constructor invokes the inductive type with +the same parameter values of its specification. + +.. example:: + + A typical example is the definition of polymorphic lists: + + .. coqtop:: all + + Inductive list (A:Set) : Set := + | nil : list A + | cons : A -> list A -> list A. + + In the type of :g:`nil` and :g:`cons`, we write ":g:`list A`" and not + just ":g:`list`". The constructors :g:`nil` and :g:`cons` have these types: + + .. coqtop:: all + + Check nil. + Check cons. + + Observe that the destructors are also quantified with :g:`(A:Set)`, for example: + + .. coqtop:: all + + Check list_ind. + + Once again, the types of the constructor arguments and of the conclusion can be omitted: + + .. coqtop:: none + + Reset list. + + .. coqtop:: in + + Inductive list (A:Set) : Set := nil | cons (_:A) (_:list A). + +.. note:: + + The constructor type can + recursively invoke the inductive definition on an argument which is not + the parameter itself. + + One can define : + + .. coqtop:: all + + Inductive list2 (A:Set) : Set := + | nil2 : list2 A + | cons2 : A -> list2 (A*A) -> list2 A. + + that can also be written by specifying only the type of the arguments: + + .. coqtop:: all reset + + Inductive list2 (A:Set) : Set := + | nil2 + | cons2 (_:A) (_:list2 (A*A)). + + But the following definition will give an error: + + .. coqtop:: all + + Fail Inductive listw (A:Set) : Set := + | nilw : listw (A*A) + | consw : A -> listw (A*A) -> listw (A*A). + + because the conclusion of the type of constructors should be :g:`listw A` + in both cases. + + + A parameterized inductive definition can be defined using annotations + instead of parameters but it will sometimes give a different (bigger) + sort for the inductive definition and will produce a less convenient + rule for case elimination. + +.. flag:: Uniform Inductive Parameters + + When this flag is set (it is off by default), + inductive definitions are abstracted over their parameters + before type checking constructors, allowing to write: + + .. coqtop:: all + + Set Uniform Inductive Parameters. + Inductive list3 (A:Set) : Set := + | nil3 : list3 + | cons3 : A -> list3 -> list3. + + This behavior is essentially equivalent to starting a new section + and using :cmd:`Context` to give the uniform parameters, like so + (cf. :ref:`section-mechanism`): + + .. coqtop:: all reset + + Section list3. + Context (A:Set). + Inductive list3 : Set := + | nil3 : list3 + | cons3 : A -> list3 -> list3. + End list3. + + For finer control, you can use a ``|`` between the uniform and + the non-uniform parameters: + + .. coqtop:: in reset + + Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop + := Acc_in : (forall y, R y x -> Acc y) -> Acc x. + + The flag can then be seen as deciding whether the ``|`` is at the + beginning (when the flag is unset) or at the end (when it is set) + of the parameters when not explicitly given. + +.. seealso:: + Section :ref:`inductive-definitions` and the :tacn:`induction` tactic. + +.. _mutually_inductive_types: + +Mutually defined inductive types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. example:: Mutually defined inductive types + + A typical example of mutually inductive data types is trees and + forests. We assume two types :g:`A` and :g:`B` that are given as variables. The types can + be declared like this: + + .. coqtop:: in + + Parameters A B : Set. + + Inductive tree : Set := node : A -> forest -> tree + + with forest : Set := + | leaf : B -> forest + | cons : tree -> forest -> forest. + + This declaration automatically generates eight induction principles. They are not the most + general principles, but they correspond to each inductive part seen as a single inductive definition. + + To illustrate this point on our example, here are the types of :g:`tree_rec` + and :g:`forest_rec`. + + .. coqtop:: all + + Check tree_rec. + + Check forest_rec. + + Assume we want to parameterize our mutual inductive definitions with the + two type variables :g:`A` and :g:`B`, the declaration should be + done as follows: + + .. coqdoc:: + + Inductive tree (A B:Set) : Set := node : A -> forest A B -> tree A B + + with forest (A B:Set) : Set := + | leaf : B -> forest A B + | cons : tree A B -> forest A B -> forest A B. + + Assume we define an inductive definition inside a section + (cf. :ref:`section-mechanism`). When the section is closed, the variables + declared in the section and occurring free in the declaration are added as + parameters to the inductive definition. + +.. seealso:: + A generic command :cmd:`Scheme` is useful to build automatically various + mutual induction principles. + +.. [1] + Except if the inductive type is empty in which case there is no + equation that can be used to infer the return type. diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst deleted file mode 100644 index b64c0aea95..0000000000 --- a/doc/sphinx/language/gallina-specification-language.rst +++ /dev/null @@ -1,335 +0,0 @@ -.. _gallina-inductive-definitions: - -Inductive types ---------------- - -.. cmd:: Inductive @inductive_definition {* with @inductive_definition } - - .. insertprodn inductive_definition constructor - - .. prodn:: - inductive_definition ::= {? > } @ident_decl {* @binder } {? %| {* @binder } } {? : @type } {? := {? @constructors_or_record } } {? @decl_notations } - constructors_or_record ::= {? %| } {+| @constructor } - | {? @ident } %{ {*; @record_field } %} - constructor ::= @ident {* @binder } {? @of_type } - - This command defines one or more - inductive types and its constructors. Coq generates destructors - depending on the universe that the inductive type belongs to. - - The destructors are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, - :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``, which - respectively correspond to elimination principles on :g:`Type`, :g:`Prop`, - :g:`Set` and :g:`SProp`. The type of the destructors - expresses structural induction/recursion principles over objects of - type :n:`@ident`. The constant :n:`@ident`\ ``_ind`` is always - generated, whereas :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_rect`` - may be impossible to derive (for example, when :n:`@ident` is a - proposition). - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - Mutually inductive types can be defined by including multiple :n:`@inductive_definition`\s. - The :n:`@ident`\s are simultaneously added to the environment before the types of constructors are checked. - Each :n:`@ident` can be used independently thereafter. - See :ref:`mutually_inductive_types`. - - If the entire inductive definition is parameterized with :n:`@binder`\s, the parameters correspond - to a local context in which the entire set of inductive declarations is interpreted. - For this reason, the parameters must be strictly the same for each inductive type. - See :ref:`parametrized-inductive-types`. - - Constructor :n:`@ident`\s can come with :n:`@binder`\s, in which case - the actual type of the constructor is :n:`forall {* @binder }, @type`. - - .. exn:: Non strictly positive occurrence of @ident in @type. - - The types of the constructors have to satisfy a *positivity condition* - (see Section :ref:`positivity`). This condition ensures the soundness of - the inductive definition. The positivity checking can be disabled using - the :flag:`Positivity Checking` flag (see :ref:`controlling-typing-flags`). - - .. exn:: The conclusion of @type is not valid; it must be built from @ident. - - The conclusion of the type of the constructors must be the inductive type - :n:`@ident` being defined (or :n:`@ident` applied to arguments in - the case of annotated inductive types — cf. next section). - -The following subsections show examples of simple inductive types, -simple annotated inductive types, simple parametric inductive types, -mutually inductive types and private (matching) inductive types. - -.. _simple-inductive-types: - -Simple inductive types -~~~~~~~~~~~~~~~~~~~~~~ - -A simple inductive type belongs to a universe that is a simple :n:`@sort`. - -.. example:: - - The set of natural numbers is defined as: - - .. coqtop:: reset all - - Inductive nat : Set := - | O : nat - | S : nat -> nat. - - The type nat is defined as the least :g:`Set` containing :g:`O` and closed by - the :g:`S` constructor. The names :g:`nat`, :g:`O` and :g:`S` are added to the - environment. - - This definition generates four elimination principles: - :g:`nat_rect`, :g:`nat_ind`, :g:`nat_rec` and :g:`nat_sind`. The type of :g:`nat_ind` is: - - .. coqtop:: all - - Check nat_ind. - - This is the well known structural induction principle over natural - numbers, i.e. the second-order form of Peano’s induction principle. It - allows proving universal properties of natural numbers (:g:`forall - n:nat, P n`) by induction on :g:`n`. - - The types of :g:`nat_rect`, :g:`nat_rec` and :g:`nat_sind` are similar, except that they - apply to, respectively, :g:`(P:nat->Type)`, :g:`(P:nat->Set)` and :g:`(P:nat->SProp)`. They correspond to - primitive induction principles (allowing dependent types) respectively - over sorts ```Type``, ``Set`` and ``SProp``. - -In the case where inductive types don't have annotations (the next section -gives an example of annotations), a constructor can be defined -by giving the type of its arguments alone. - -.. example:: - - .. coqtop:: reset none - - Reset nat. - - .. coqtop:: in - - Inductive nat : Set := O | S (_:nat). - -Simple annotated inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In annotated inductive types, the universe where the inductive type -is defined is no longer a simple :n:`@sort`, but what is called an arity, -which is a type whose conclusion is a :n:`@sort`. - -.. example:: - - As an example of annotated inductive types, let us define the - :g:`even` predicate: - - .. coqtop:: all - - Inductive even : nat -> Prop := - | even_0 : even O - | even_SS : forall n:nat, even n -> even (S (S n)). - - The type :g:`nat->Prop` means that :g:`even` is a unary predicate (inductively - defined) over natural numbers. The type of its two constructors are the - defining clauses of the predicate :g:`even`. The type of :g:`even_ind` is: - - .. coqtop:: all - - Check even_ind. - - From a mathematical point of view, this asserts that the natural numbers satisfying - the predicate :g:`even` are exactly in the smallest set of naturals satisfying the - clauses :g:`even_0` or :g:`even_SS`. This is why, when we want to prove any - predicate :g:`P` over elements of :g:`even`, it is enough to prove it for :g:`O` - and to prove that if any natural number :g:`n` satisfies :g:`P` its double - successor :g:`(S (S n))` satisfies also :g:`P`. This is analogous to the - structural induction principle we got for :g:`nat`. - -.. _parametrized-inductive-types: - -Parameterized inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the previous example, each constructor introduces a different -instance of the predicate :g:`even`. In some cases, all the constructors -introduce the same generic instance of the inductive definition, in -which case, instead of an annotation, we use a context of parameters -which are :n:`@binder`\s shared by all the constructors of the definition. - -Parameters differ from inductive type annotations in that the -conclusion of each type of constructor invokes the inductive type with -the same parameter values of its specification. - -.. example:: - - A typical example is the definition of polymorphic lists: - - .. coqtop:: all - - Inductive list (A:Set) : Set := - | nil : list A - | cons : A -> list A -> list A. - - In the type of :g:`nil` and :g:`cons`, we write ":g:`list A`" and not - just ":g:`list`". The constructors :g:`nil` and :g:`cons` have these types: - - .. coqtop:: all - - Check nil. - Check cons. - - Observe that the destructors are also quantified with :g:`(A:Set)`, for example: - - .. coqtop:: all - - Check list_ind. - - Once again, the types of the constructor arguments and of the conclusion can be omitted: - - .. coqtop:: none - - Reset list. - - .. coqtop:: in - - Inductive list (A:Set) : Set := nil | cons (_:A) (_:list A). - -.. note:: - + The constructor type can - recursively invoke the inductive definition on an argument which is not - the parameter itself. - - One can define : - - .. coqtop:: all - - Inductive list2 (A:Set) : Set := - | nil2 : list2 A - | cons2 : A -> list2 (A*A) -> list2 A. - - that can also be written by specifying only the type of the arguments: - - .. coqtop:: all reset - - Inductive list2 (A:Set) : Set := - | nil2 - | cons2 (_:A) (_:list2 (A*A)). - - But the following definition will give an error: - - .. coqtop:: all - - Fail Inductive listw (A:Set) : Set := - | nilw : listw (A*A) - | consw : A -> listw (A*A) -> listw (A*A). - - because the conclusion of the type of constructors should be :g:`listw A` - in both cases. - - + A parameterized inductive definition can be defined using annotations - instead of parameters but it will sometimes give a different (bigger) - sort for the inductive definition and will produce a less convenient - rule for case elimination. - -.. flag:: Uniform Inductive Parameters - - When this flag is set (it is off by default), - inductive definitions are abstracted over their parameters - before type checking constructors, allowing to write: - - .. coqtop:: all - - Set Uniform Inductive Parameters. - Inductive list3 (A:Set) : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - - This behavior is essentially equivalent to starting a new section - and using :cmd:`Context` to give the uniform parameters, like so - (cf. :ref:`section-mechanism`): - - .. coqtop:: all reset - - Section list3. - Context (A:Set). - Inductive list3 : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - End list3. - - For finer control, you can use a ``|`` between the uniform and - the non-uniform parameters: - - .. coqtop:: in reset - - Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop - := Acc_in : (forall y, R y x -> Acc y) -> Acc x. - - The flag can then be seen as deciding whether the ``|`` is at the - beginning (when the flag is unset) or at the end (when it is set) - of the parameters when not explicitly given. - -.. seealso:: - Section :ref:`inductive-definitions` and the :tacn:`induction` tactic. - -.. _mutually_inductive_types: - -Mutually defined inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. example:: Mutually defined inductive types - - A typical example of mutually inductive data types is trees and - forests. We assume two types :g:`A` and :g:`B` that are given as variables. The types can - be declared like this: - - .. coqtop:: in - - Parameters A B : Set. - - Inductive tree : Set := node : A -> forest -> tree - - with forest : Set := - | leaf : B -> forest - | cons : tree -> forest -> forest. - - This declaration automatically generates eight induction principles. They are not the most - general principles, but they correspond to each inductive part seen as a single inductive definition. - - To illustrate this point on our example, here are the types of :g:`tree_rec` - and :g:`forest_rec`. - - .. coqtop:: all - - Check tree_rec. - - Check forest_rec. - - Assume we want to parameterize our mutual inductive definitions with the - two type variables :g:`A` and :g:`B`, the declaration should be - done as follows: - - .. coqdoc:: - - Inductive tree (A B:Set) : Set := node : A -> forest A B -> tree A B - - with forest (A B:Set) : Set := - | leaf : B -> forest A B - | cons : tree A B -> forest A B -> forest A B. - - Assume we define an inductive definition inside a section - (cf. :ref:`section-mechanism`). When the section is closed, the variables - declared in the section and occurring free in the declaration are added as - parameters to the inductive definition. - -.. seealso:: - A generic command :cmd:`Scheme` is useful to build automatically various - mutual induction principles. - -.. [1] - Except if the inductive type is empty in which case there is no - equation that can be used to infer the return type. -- cgit v1.2.3 From f0cc07bef6f7133425c3ec3542f6f214c9e1a0a1 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 20:06:35 +0200 Subject: Extract Recursive functions from Gallina. --- .../language/gallina-specification-language.rst | 1288 +------------------- 1 file changed, 5 insertions(+), 1283 deletions(-) diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst index 353bed1b3d..6e5417535a 100644 --- a/doc/sphinx/language/gallina-specification-language.rst +++ b/doc/sphinx/language/gallina-specification-language.rst @@ -1,432 +1,8 @@ -.. _gallinaspecificationlanguage: - ------------------------------------- - The Gallina specification language ------------------------------------- - -This chapter describes Gallina, the specification language of Coq. It allows -developing mathematical theories and to prove specifications of programs. The -theories are built from axioms, hypotheses, parameters, lemmas, theorems and -definitions of constants, functions, predicates and sets. - -.. _term: - -Terms -===== - -.. _gallina-identifiers: - -Qualified identifiers and simple identifiers --------------------------------------------- - -.. insertprodn qualid field_ident - -.. prodn:: - qualid ::= @ident {* @field_ident } - field_ident ::= .@ident - -*Qualified identifiers* (:n:`@qualid`) denote *global constants* -(definitions, lemmas, theorems, remarks or facts), *global variables* -(parameters or axioms), *inductive types* or *constructors of inductive -types*. *Simple identifiers* (or shortly :n:`@ident`) are a syntactic subset -of qualified identifiers. Identifiers may also denote *local variables*, -while qualified identifiers do not. - -Field identifiers, written :n:`@field_ident`, are identifiers prefixed by -`.` (dot) with no blank between the dot and the identifier. - - -Numerals and strings --------------------- - -.. insertprodn primitive_notations primitive_notations - -.. prodn:: - primitive_notations ::= @numeral - | @string - -Numerals and strings have no predefined semantics in the calculus. They are -merely notations that can be bound to objects through the notation mechanism -(see Chapter :ref:`syntax-extensions-and-notation-scopes` for details). -Initially, numerals are bound to Peano’s representation of natural -numbers (see :ref:`datatypes`). - -.. note:: - - Negative integers are not at the same level as :n:`@num`, for this - would make precedence unnatural. - -.. index:: - single: Set (sort) - single: SProp - single: Prop - single: Type - -Sorts ------ - -.. insertprodn sort univ_constraint - -.. prodn:: - sort ::= Set - | Prop - | SProp - | Type - | Type @%{ _ %} - | Type @%{ @universe %} - universe ::= max ( {+, @universe_expr } ) - | @universe_expr - universe_expr ::= @universe_name {? + @num } - universe_name ::= @qualid - | Set - | Prop - univ_annot ::= @%{ {* @universe_level } %} - universe_level ::= Set - | Prop - | Type - | _ - | @qualid - univ_decl ::= @%{ {* @ident } {? + } {? %| {*, @univ_constraint } {? + } } %} - univ_constraint ::= @universe_name {| < | = | <= } @universe_name - -There are four sorts :g:`SProp`, :g:`Prop`, :g:`Set` and :g:`Type`. - -- :g:`SProp` is the universe of *definitionally irrelevant - propositions* (also called *strict propositions*). - -- :g:`Prop` is the universe of *logical propositions*. The logical propositions - themselves are typing the proofs. We denote propositions by :n:`@form`. - This constitutes a semantic subclass of the syntactic class :n:`@term`. - -- :g:`Set` is the universe of *program types* or *specifications*. The - specifications themselves are typing the programs. We denote - specifications by :n:`@specif`. This constitutes a semantic subclass of - the syntactic class :n:`@term`. - -- :g:`Type` is the type of sorts. - -More on sorts can be found in Section :ref:`sorts`. - -.. _binders: - -Binders -------- - -.. insertprodn open_binders binder - -.. prodn:: - open_binders ::= {+ @name } : @term - | {+ @binder } - name ::= _ - | @ident - binder ::= @name - | ( {+ @name } : @type ) - | ( @name {? : @type } := @term ) - | @implicit_binders - | @generalizing_binder - | ( @name : @type %| @term ) - | ' @pattern0 - -Various constructions such as :g:`fun`, :g:`forall`, :g:`fix` and :g:`cofix` -*bind* variables. A binding is represented by an identifier. If the binding -variable is not used in the expression, the identifier can be replaced by the -symbol :g:`_`. When the type of a bound variable cannot be synthesized by the -system, it can be specified with the notation :n:`(@ident : @type)`. There is also -a notation for a sequence of binding variables sharing the same type: -:n:`({+ @ident} : @type)`. A -binder can also be any pattern prefixed by a quote, e.g. :g:`'(x,y)`. - -Some constructions allow the binding of a variable to value. This is -called a “let-binder”. The entry :n:`@binder` of the grammar accepts -either an assumption binder as defined above or a let-binder. The notation in -the latter case is :n:`(@ident := @term)`. In a let-binder, only one -variable can be introduced at the same time. It is also possible to give -the type of the variable as follows: -:n:`(@ident : @type := @term)`. - -Lists of :n:`@binder`\s are allowed. In the case of :g:`fun` and :g:`forall`, -it is intended that at least one binder of the list is an assumption otherwise -fun and forall gets identical. Moreover, parentheses can be omitted in -the case of a single sequence of bindings sharing the same type (e.g.: -:g:`fun (x y z : A) => t` can be shortened in :g:`fun x y z : A => t`). - -.. index:: fun ... => ... - -Abstractions: fun ------------------ - -The expression :n:`fun @ident : @type => @term` defines the -*abstraction* of the variable :n:`@ident`, of type :n:`@type`, over the term -:n:`@term`. It denotes a function of the variable :n:`@ident` that evaluates to -the expression :n:`@term` (e.g. :g:`fun x : A => x` denotes the identity -function on type :g:`A`). The keyword :g:`fun` can be followed by several -binders as given in Section :ref:`binders`. Functions over -several variables are equivalent to an iteration of one-variable -functions. For instance the expression -:n:`fun {+ @ident__i } : @type => @term` -denotes the same function as :n:`{+ fun @ident__i : @type => } @term`. If -a let-binder occurs in -the list of binders, it is expanded to a let-in definition (see -Section :ref:`let-in`). - -.. index:: forall - -Products: forall ----------------- - -.. insertprodn term_forall_or_fun term_forall_or_fun - -.. prodn:: - term_forall_or_fun ::= forall @open_binders , @term - | fun @open_binders => @term - -The expression :n:`forall @ident : @type, @term` denotes the -*product* of the variable :n:`@ident` of type :n:`@type`, over the term :n:`@term`. -As for abstractions, :g:`forall` is followed by a binder list, and products -over several variables are equivalent to an iteration of one-variable -products. Note that :n:`@term` is intended to be a type. - -If the variable :n:`@ident` occurs in :n:`@term`, the product is called -*dependent product*. The intention behind a dependent product -:g:`forall x : A, B` is twofold. It denotes either -the universal quantification of the variable :g:`x` of type :g:`A` -in the proposition :g:`B` or the functional dependent product from -:g:`A` to :g:`B` (a construction usually written -:math:`\Pi_{x:A}.B` in set theory). - -Non dependent product types have a special notation: :g:`A -> B` stands for -:g:`forall _ : A, B`. The *non dependent product* is used both to denote -the propositional implication and function types. - -Applications ------------- - -.. insertprodn term_application arg - -.. prodn:: - term_application ::= @term1 {+ @arg } - | @ @qualid_annotated {+ @term1 } - arg ::= ( @ident := @term ) - | @term1 - -:n:`@term__fun @term` denotes applying the function :n:`@term__fun` to :token:`term`. - -:n:`@term__fun {+ @term__i }` denotes applying -:n:`@term__fun` to the arguments :n:`@term__i`. It is -equivalent to :n:`( … ( @term__fun @term__1 ) … ) @term__n`: -associativity is to the left. - -The notation :n:`(@ident := @term)` for arguments is used for making -explicit the value of implicit arguments (see -Section :ref:`explicit-applications`). - -.. index:: - single: ... : ... (type cast) - single: ... <: ... - single: ... <<: ... - -Type cast ---------- - -.. insertprodn term_cast term_cast - -.. prodn:: - term_cast ::= @term10 <: @term - | @term10 <<: @term - | @term10 : @term - | @term10 :> - -The expression :n:`@term : @type` is a type cast expression. It enforces -the type of :n:`@term` to be :n:`@type`. - -:n:`@term <: @type` locally sets up the virtual machine for checking that -:n:`@term` has type :n:`@type`. - -:n:`@term <<: @type` uses native compilation for checking that :n:`@term` -has type :n:`@type`. - -.. index:: _ - -Inferable subterms ------------------- - -Expressions often contain redundant pieces of information. Subterms that can be -automatically inferred by Coq can be replaced by the symbol ``_`` and Coq will -guess the missing piece of information. - -.. index:: let ... := ... (term) - -.. _let-in: - -Let-in definitions ------------------- - -.. insertprodn term_let term_let - -.. prodn:: - term_let ::= let @name {? : @type } := @term in @term - | let @name {+ @binder } {? : @type } := @term in @term - | let ( {*, @name } ) {? {? as @name } return @term100 } := @term in @term - | let ' @pattern := @term {? return @term100 } in @term - | let ' @pattern in @pattern := @term return @term100 in @term - -:n:`let @ident := @term in @term’` -denotes the local binding of :n:`@term` to the variable -:n:`@ident` in :n:`@term`’. There is a syntactic sugar for let-in -definition of functions: :n:`let @ident {+ @binder} := @term in @term’` -stands for :n:`let @ident := fun {+ @binder} => @term in @term’`. - -.. index:: match ... with ... - -Definition by cases: match --------------------------- - -.. insertprodn term_match pattern0 - -.. prodn:: - term_match ::= match {+, @case_item } {? return @term100 } with {? %| } {*| @eqn } end - case_item ::= @term100 {? as @name } {? in @pattern } - eqn ::= {+| {+, @pattern } } => @term - pattern ::= @pattern10 : @term - | @pattern10 - pattern10 ::= @pattern1 as @name - | @pattern1 {* @pattern1 } - | @ @qualid {* @pattern1 } - pattern1 ::= @pattern0 % @scope_key - | @pattern0 - pattern0 ::= @qualid - | %{%| {* @qualid := @pattern } %|%} - | _ - | ( {+| @pattern } ) - | @numeral - | @string - -Objects of inductive types can be destructured by a case-analysis -construction called *pattern matching* expression. A pattern matching -expression is used to analyze the structure of an inductive object and -to apply specific treatments accordingly. - -This paragraph describes the basic form of pattern matching. See -Section :ref:`Mult-match` and Chapter :ref:`extendedpatternmatching` for the description -of the general form. The basic form of pattern matching is characterized -by a single :n:`@case_item` expression, an :n:`@eqn` restricted to a -single :n:`@pattern` and :n:`@pattern` restricted to the form -:n:`@qualid {* @ident}`. - -The expression -:n:`match @term {? return @term100 } with {+| @pattern__i => @term__i } end` denotes a -*pattern matching* over the term :n:`@term` (expected to be -of an inductive type :math:`I`). The :n:`@term__i` -are the *branches* of the pattern matching -expression. Each :n:`@pattern__i` has the form :n:`@qualid @ident` -where :n:`@qualid` must denote a constructor. There should be -exactly one branch for every constructor of :math:`I`. - -The :n:`return @term100` clause gives the type returned by the whole match -expression. There are several cases. In the *non dependent* case, all -branches have the same type, and the :n:`return @term100` specifies that type. -In this case, :n:`return @term100` can usually be omitted as it can be -inferred from the type of the branches [1]_. - -In the *dependent* case, there are three subcases. In the first subcase, -the type in each branch may depend on the exact value being matched in -the branch. In this case, the whole pattern matching itself depends on -the term being matched. This dependency of the term being matched in the -return type is expressed with an :n:`@ident` clause where :n:`@ident` -is dependent in the return type. For instance, in the following example: - -.. coqtop:: in - - Inductive bool : Type := true : bool | false : bool. - Inductive eq (A:Type) (x:A) : A -> Prop := eq_refl : eq A x x. - Inductive or (A:Prop) (B:Prop) : Prop := - | or_introl : A -> or A B - | or_intror : B -> or A B. - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b as x return or (eq bool x true) (eq bool x false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -the branches have respective types ":g:`or (eq bool true true) (eq bool true false)`" -and ":g:`or (eq bool false true) (eq bool false false)`" while the whole -pattern matching expression has type ":g:`or (eq bool b true) (eq bool b false)`", -the identifier :g:`b` being used to represent the dependency. - -.. note:: - - When the term being matched is a variable, the ``as`` clause can be - omitted and the term being matched can serve itself as binding name in - the return type. For instance, the following alternative definition is - accepted and has the same meaning as the previous one. - - .. coqtop:: none - - Reset bool_case. - - .. coqtop:: in - - Definition bool_case (b:bool) : or (eq bool b true) (eq bool b false) := - match b return or (eq bool b true) (eq bool b false) with - | true => or_introl (eq bool true true) (eq bool true false) (eq_refl bool true) - | false => or_intror (eq bool false true) (eq bool false false) (eq_refl bool false) - end. - -The second subcase is only relevant for annotated inductive types such -as the equality predicate (see Section :ref:`coq-equality`), -the order predicate on natural numbers or the type of lists of a given -length (see Section :ref:`matching-dependent`). In this configuration, the -type of each branch can depend on the type dependencies specific to the -branch and the whole pattern matching expression has a type determined -by the specific dependencies in the type of the term being matched. This -dependency of the return type in the annotations of the inductive type -is expressed with a clause in the form -:n:`in @qualid {+ _ } {+ @pattern }`, where - -- :n:`@qualid` is the inductive type of the term being matched; - -- the holes :n:`_` match the parameters of the inductive type: the - return type is not dependent on them. - -- each :n:`@pattern` matches the annotations of the - inductive type: the return type is dependent on them - -- in the basic case which we describe below, each :n:`@pattern` - is a name :n:`@ident`; see :ref:`match-in-patterns` for the - general case - -For instance, in the following example: - -.. coqtop:: in - - Definition eq_sym (A:Type) (x y:A) (H:eq A x y) : eq A y x := - match H in eq _ _ z return eq A z x with - | eq_refl _ _ => eq_refl A x - end. - -the type of the branch is :g:`eq A x x` because the third argument of -:g:`eq` is :g:`x` in the type of the pattern :g:`eq_refl`. On the contrary, the -type of the whole pattern matching expression has type :g:`eq A y x` because the -third argument of eq is y in the type of H. This dependency of the case analysis -in the third argument of :g:`eq` is expressed by the identifier :g:`z` in the -return type. - -Finally, the third subcase is a combination of the first and second -subcase. In particular, it only applies to pattern matching on terms in -a type with annotations. For this third subcase, both the clauses ``as`` and -``in`` are available. - -There are specific notations for case analysis on types with one or two -constructors: ``if … then … else …`` and ``let (…,…) := … in …`` (see -Sections :ref:`if-then-else` and :ref:`irrefutable-patterns`). - .. index:: single: fix - single: cofix -Recursive and co-recursive functions: fix and cofix ---------------------------------------------------- +Recursive functions: fix +------------------------ .. insertprodn term_fix fixannot @@ -452,669 +28,15 @@ Some options of :n:`@fixannot` are only supported in specific constructs. :n:`f only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. -.. insertprodn term_cofix cofix_body - -.. prodn:: - term_cofix ::= let cofix @cofix_body in @term - | cofix @cofix_body {? {+ with @cofix_body } for @ident } - cofix_body ::= @ident {* @binder } {? : @type } := @term - -The expression -":n:`cofix @ident__1 @binder__1 : @type__1 with … with @ident__n @binder__n : @type__n for @ident__i`" -denotes the :math:`i`-th component of a block of terms defined by a mutual guarded -co-recursion. It is the local counterpart of the :cmd:`CoFixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -.. _vernacular: - -The Vernacular -============== - -.. _gallina-assumptions: - -Assumptions ------------ - -Assumptions extend the environment with axioms, parameters, hypotheses -or variables. An assumption binds an :n:`@ident` to a :n:`@type`. It is accepted -by Coq if and only if this :n:`@type` is a correct type in the environment -preexisting the declaration and if :n:`@ident` was not previously defined in -the same module. This :n:`@type` is considered to be the type (or -specification, or statement) assumed by :n:`@ident` and we say that :n:`@ident` -has type :n:`@type`. - -.. _Axiom: - -.. cmd:: @assumption_token {? Inline {? ( @num ) } } {| {+ ( @assumpt ) } | @assumpt } - :name: Axiom; Axioms; Conjecture; Conjectures; Hypothesis; Hypotheses; Parameter; Parameters; Variable; Variables - - .. insertprodn assumption_token of_type - - .. prodn:: - assumption_token ::= {| Axiom | Axioms } - | {| Conjecture | Conjectures } - | {| Parameter | Parameters } - | {| Hypothesis | Hypotheses } - | {| Variable | Variables } - assumpt ::= {+ @ident_decl } @of_type - ident_decl ::= @ident {? @univ_decl } - of_type ::= {| : | :> | :>> } @type - - These commands bind one or more :n:`@ident`\(s) to specified :n:`@type`\(s) as their specifications in - the global context. The fact asserted by the :n:`@type` (or, equivalently, the existence - of an object of this type) is accepted as a postulate. - - :cmd:`Axiom`, :cmd:`Conjecture`, :cmd:`Parameter` and their plural forms - are equivalent. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident`\s accessible by :cmd:`Import` and its variants - only through their fully qualified names. - - Similarly, :cmd:`Hypothesis`, :cmd:`Variable` and their plural forms are equivalent. Outside - of a section, these are equivalent to :n:`Local Parameter`. Inside a section, the - :n:`@ident`\s defined are only accessible within the section. When the current section - is closed, the :n:`@ident`\(s) become undefined and every object depending on them will be explicitly - parameterized (i.e., the variables are *discharged*). See Section :ref:`section-mechanism`. - - The :n:`Inline` clause is only relevant inside functors. See :cmd:`Module`. - -.. example:: Simple assumptions - - .. coqtop:: reset in - - Parameter X Y : Set. - Parameter (R : X -> Y -> Prop) (S : Y -> X -> Prop). - Axiom R_S_inv : forall x y, R x y <-> S y x. - -.. exn:: @ident already exists. - :name: @ident already exists. (Axiom) - :undocumented: - -.. warn:: @ident is declared as a local axiom - - Warning generated when using :cmd:`Variable` or its equivalent - instead of :n:`Local Parameter` or its equivalent. - -.. note:: - We advise using the commands :cmd:`Axiom`, :cmd:`Conjecture` and - :cmd:`Hypothesis` (and their plural forms) for logical postulates (i.e. when - the assertion :n:`@type` is of sort :g:`Prop`), and to use the commands - :cmd:`Parameter` and :cmd:`Variable` (and their plural forms) in other cases - (corresponding to the declaration of an abstract object of the given type). - -.. _gallina-definitions: - -Definitions ------------ - -Definitions extend the environment with associations of names to terms. -A definition can be seen as a way to give a meaning to a name or as a -way to abbreviate a term. In any case, the name can later be replaced at -any time by its definition. - -The operation of unfolding a name into its definition is called -:math:`\delta`-conversion (see Section :ref:`delta-reduction`). A -definition is accepted by the system if and only if the defined term is -well-typed in the current context of the definition and if the name is -not already used. The name defined by the definition is called a -*constant* and the term it refers to is its *body*. A definition has a -type which is the type of its body. - -A formal presentation of constants and environments is given in -Section :ref:`typing-rules`. - -.. cmd:: {| Definition | Example } @ident_decl @def_body - :name: Definition; Example - - .. insertprodn def_body def_body - - .. prodn:: - def_body ::= {* @binder } {? : @type } := {? @reduce } @term - | {* @binder } : @type - - These commands bind :n:`@term` to the name :n:`@ident` in the environment, - provided that :n:`@term` is well-typed. They can take the :attr:`local` :term:`attribute`, - which makes the defined :n:`@ident` accessible by :cmd:`Import` and its variants - only through their fully qualified names. - If :n:`@reduce` is present then :n:`@ident` is bound to the result of the specified - computation on :n:`@term`. - - These commands also support the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`program` and - :attr:`canonical` attributes. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - The form :n:`Definition @ident : @type := @term` checks that the type of :n:`@term` - is definitionally equal to :n:`@type`, and registers :n:`@ident` as being of type - :n:`@type`, and bound to value :n:`@term`. - - The form :n:`Definition @ident {* @binder } : @type := @term` is equivalent to - :n:`Definition @ident : forall {* @binder }, @type := fun {* @binder } => @term`. - - .. seealso:: :cmd:`Opaque`, :cmd:`Transparent`, :tacn:`unfold`. - - .. exn:: @ident already exists. - :name: @ident already exists. (Definition) - :undocumented: - - .. exn:: The term @term has type @type while it is expected to have type @type'. - :undocumented: - -.. _gallina-inductive-definitions: - -Inductive types ---------------- - -.. cmd:: Inductive @inductive_definition {* with @inductive_definition } - - .. insertprodn inductive_definition constructor - - .. prodn:: - inductive_definition ::= {? > } @ident_decl {* @binder } {? %| {* @binder } } {? : @type } {? := {? @constructors_or_record } } {? @decl_notations } - constructors_or_record ::= {? %| } {+| @constructor } - | {? @ident } %{ {*; @record_field } %} - constructor ::= @ident {* @binder } {? @of_type } - - This command defines one or more - inductive types and its constructors. Coq generates destructors - depending on the universe that the inductive type belongs to. - - The destructors are named :n:`@ident`\ ``_rect``, :n:`@ident`\ ``_ind``, - :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_sind``, which - respectively correspond to elimination principles on :g:`Type`, :g:`Prop`, - :g:`Set` and :g:`SProp`. The type of the destructors - expresses structural induction/recursion principles over objects of - type :n:`@ident`. The constant :n:`@ident`\ ``_ind`` is always - generated, whereas :n:`@ident`\ ``_rec`` and :n:`@ident`\ ``_rect`` - may be impossible to derive (for example, when :n:`@ident` is a - proposition). - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - Mutually inductive types can be defined by including multiple :n:`@inductive_definition`\s. - The :n:`@ident`\s are simultaneously added to the environment before the types of constructors are checked. - Each :n:`@ident` can be used independently thereafter. - See :ref:`mutually_inductive_types`. - - If the entire inductive definition is parameterized with :n:`@binder`\s, the parameters correspond - to a local context in which the entire set of inductive declarations is interpreted. - For this reason, the parameters must be strictly the same for each inductive type. - See :ref:`parametrized-inductive-types`. - - Constructor :n:`@ident`\s can come with :n:`@binder`\s, in which case - the actual type of the constructor is :n:`forall {* @binder }, @type`. - - .. exn:: Non strictly positive occurrence of @ident in @type. - - The types of the constructors have to satisfy a *positivity condition* - (see Section :ref:`positivity`). This condition ensures the soundness of - the inductive definition. The positivity checking can be disabled using - the :flag:`Positivity Checking` flag (see :ref:`controlling-typing-flags`). - - .. exn:: The conclusion of @type is not valid; it must be built from @ident. - - The conclusion of the type of the constructors must be the inductive type - :n:`@ident` being defined (or :n:`@ident` applied to arguments in - the case of annotated inductive types — cf. next section). - -The following subsections show examples of simple inductive types, -simple annotated inductive types, simple parametric inductive types, -mutually inductive types and private (matching) inductive types. - -.. _simple-inductive-types: - -Simple inductive types -~~~~~~~~~~~~~~~~~~~~~~ - -A simple inductive type belongs to a universe that is a simple :n:`@sort`. - -.. example:: - - The set of natural numbers is defined as: - - .. coqtop:: reset all - - Inductive nat : Set := - | O : nat - | S : nat -> nat. - - The type nat is defined as the least :g:`Set` containing :g:`O` and closed by - the :g:`S` constructor. The names :g:`nat`, :g:`O` and :g:`S` are added to the - environment. - - This definition generates four elimination principles: - :g:`nat_rect`, :g:`nat_ind`, :g:`nat_rec` and :g:`nat_sind`. The type of :g:`nat_ind` is: - - .. coqtop:: all - - Check nat_ind. - - This is the well known structural induction principle over natural - numbers, i.e. the second-order form of Peano’s induction principle. It - allows proving universal properties of natural numbers (:g:`forall - n:nat, P n`) by induction on :g:`n`. - - The types of :g:`nat_rect`, :g:`nat_rec` and :g:`nat_sind` are similar, except that they - apply to, respectively, :g:`(P:nat->Type)`, :g:`(P:nat->Set)` and :g:`(P:nat->SProp)`. They correspond to - primitive induction principles (allowing dependent types) respectively - over sorts ```Type``, ``Set`` and ``SProp``. - -In the case where inductive types don't have annotations (the next section -gives an example of annotations), a constructor can be defined -by giving the type of its arguments alone. - -.. example:: - - .. coqtop:: reset none - - Reset nat. - - .. coqtop:: in - - Inductive nat : Set := O | S (_:nat). - -Simple annotated inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In annotated inductive types, the universe where the inductive type -is defined is no longer a simple :n:`@sort`, but what is called an arity, -which is a type whose conclusion is a :n:`@sort`. - -.. example:: - - As an example of annotated inductive types, let us define the - :g:`even` predicate: - - .. coqtop:: all - - Inductive even : nat -> Prop := - | even_0 : even O - | even_SS : forall n:nat, even n -> even (S (S n)). - - The type :g:`nat->Prop` means that :g:`even` is a unary predicate (inductively - defined) over natural numbers. The type of its two constructors are the - defining clauses of the predicate :g:`even`. The type of :g:`even_ind` is: - - .. coqtop:: all - - Check even_ind. - - From a mathematical point of view, this asserts that the natural numbers satisfying - the predicate :g:`even` are exactly in the smallest set of naturals satisfying the - clauses :g:`even_0` or :g:`even_SS`. This is why, when we want to prove any - predicate :g:`P` over elements of :g:`even`, it is enough to prove it for :g:`O` - and to prove that if any natural number :g:`n` satisfies :g:`P` its double - successor :g:`(S (S n))` satisfies also :g:`P`. This is analogous to the - structural induction principle we got for :g:`nat`. - -.. _parametrized-inductive-types: - -Parameterized inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -In the previous example, each constructor introduces a different -instance of the predicate :g:`even`. In some cases, all the constructors -introduce the same generic instance of the inductive definition, in -which case, instead of an annotation, we use a context of parameters -which are :n:`@binder`\s shared by all the constructors of the definition. - -Parameters differ from inductive type annotations in that the -conclusion of each type of constructor invokes the inductive type with -the same parameter values of its specification. - -.. example:: - - A typical example is the definition of polymorphic lists: - - .. coqtop:: all - - Inductive list (A:Set) : Set := - | nil : list A - | cons : A -> list A -> list A. - - In the type of :g:`nil` and :g:`cons`, we write ":g:`list A`" and not - just ":g:`list`". The constructors :g:`nil` and :g:`cons` have these types: - - .. coqtop:: all - - Check nil. - Check cons. - - Observe that the destructors are also quantified with :g:`(A:Set)`, for example: - - .. coqtop:: all - - Check list_ind. - - Once again, the types of the constructor arguments and of the conclusion can be omitted: - - .. coqtop:: none - - Reset list. - - .. coqtop:: in - - Inductive list (A:Set) : Set := nil | cons (_:A) (_:list A). - -.. note:: - + The constructor type can - recursively invoke the inductive definition on an argument which is not - the parameter itself. - - One can define : - - .. coqtop:: all - - Inductive list2 (A:Set) : Set := - | nil2 : list2 A - | cons2 : A -> list2 (A*A) -> list2 A. - - that can also be written by specifying only the type of the arguments: - - .. coqtop:: all reset - - Inductive list2 (A:Set) : Set := - | nil2 - | cons2 (_:A) (_:list2 (A*A)). - - But the following definition will give an error: - - .. coqtop:: all - - Fail Inductive listw (A:Set) : Set := - | nilw : listw (A*A) - | consw : A -> listw (A*A) -> listw (A*A). - - because the conclusion of the type of constructors should be :g:`listw A` - in both cases. - - + A parameterized inductive definition can be defined using annotations - instead of parameters but it will sometimes give a different (bigger) - sort for the inductive definition and will produce a less convenient - rule for case elimination. - -.. flag:: Uniform Inductive Parameters - - When this flag is set (it is off by default), - inductive definitions are abstracted over their parameters - before type checking constructors, allowing to write: - - .. coqtop:: all - - Set Uniform Inductive Parameters. - Inductive list3 (A:Set) : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - - This behavior is essentially equivalent to starting a new section - and using :cmd:`Context` to give the uniform parameters, like so - (cf. :ref:`section-mechanism`): - - .. coqtop:: all reset - - Section list3. - Context (A:Set). - Inductive list3 : Set := - | nil3 : list3 - | cons3 : A -> list3 -> list3. - End list3. - - For finer control, you can use a ``|`` between the uniform and - the non-uniform parameters: - - .. coqtop:: in reset - - Inductive Acc {A:Type} (R:A->A->Prop) | (x:A) : Prop - := Acc_in : (forall y, R y x -> Acc y) -> Acc x. - - The flag can then be seen as deciding whether the ``|`` is at the - beginning (when the flag is unset) or at the end (when it is set) - of the parameters when not explicitly given. - -.. seealso:: - Section :ref:`inductive-definitions` and the :tacn:`induction` tactic. - -.. _mutually_inductive_types: - -Mutually defined inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. example:: Mutually defined inductive types - - A typical example of mutually inductive data types is trees and - forests. We assume two types :g:`A` and :g:`B` that are given as variables. The types can - be declared like this: - - .. coqtop:: in - - Parameters A B : Set. - - Inductive tree : Set := node : A -> forest -> tree - - with forest : Set := - | leaf : B -> forest - | cons : tree -> forest -> forest. - - This declaration automatically generates eight induction principles. They are not the most - general principles, but they correspond to each inductive part seen as a single inductive definition. - - To illustrate this point on our example, here are the types of :g:`tree_rec` - and :g:`forest_rec`. - - .. coqtop:: all - - Check tree_rec. - - Check forest_rec. - - Assume we want to parameterize our mutual inductive definitions with the - two type variables :g:`A` and :g:`B`, the declaration should be - done as follows: - - .. coqdoc:: - - Inductive tree (A B:Set) : Set := node : A -> forest A B -> tree A B - - with forest (A B:Set) : Set := - | leaf : B -> forest A B - | cons : tree A B -> forest A B -> forest A B. - - Assume we define an inductive definition inside a section - (cf. :ref:`section-mechanism`). When the section is closed, the variables - declared in the section and occurring free in the declaration are added as - parameters to the inductive definition. - -.. seealso:: - A generic command :cmd:`Scheme` is useful to build automatically various - mutual induction principles. - -Private (matching) inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. attr:: private(matching) - - This attribute can be used to forbid the use of the :g:`match` - construct on objects of this inductive type outside of the module - where it is defined. There is also a legacy syntax using the - ``Private`` prefix (cf. :n:`@legacy_attr`). - - The main use case of private (matching) inductive types is to emulate - quotient types / higher-order inductive types in projects such as - the `HoTT library `_. - -.. example:: - - .. coqtop:: all - - Module Foo. - #[ private(matching) ] Inductive my_nat := my_O : my_nat | my_S : my_nat -> my_nat. - Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - End Foo. - Import Foo. - Fail Check (fun x : my_nat => match x with my_O => true | my_S _ => false end). - -Variants -~~~~~~~~ - -.. cmd:: Variant @variant_definition {* with @variant_definition } - - .. insertprodn variant_definition variant_definition - - .. prodn:: - variant_definition ::= @ident_decl {* @binder } {? %| {* @binder } } {? : @type } := {? %| } {+| @constructor } {? @decl_notations } - - The :cmd:`Variant` command is similar to the :cmd:`Inductive` command, except - that it disallows recursive definition of types (for instance, lists cannot - be defined using :cmd:`Variant`). No induction scheme is generated for - this variant, unless the :flag:`Nonrecursive Elimination Schemes` flag is on. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - - .. exn:: The @num th argument of @ident must be @ident in @type. - :undocumented: - -.. _coinductive-types: - -Co-inductive types ------------------- - -The objects of an inductive type are well-founded with respect to the -constructors of the type. In other words, such objects contain only a -*finite* number of constructors. Co-inductive types arise from relaxing -this condition, and admitting types whose objects contain an infinity of -constructors. Infinite objects are introduced by a non-ending (but -effective) process of construction, defined in terms of the constructors -of the type. - -.. cmd:: CoInductive @inductive_definition {* with @inductive_definition } - - This command introduces a co-inductive type. - The syntax of the command is the same as the command :cmd:`Inductive`. - No principle of induction is derived from the definition of a co-inductive - type, since such principles only make sense for inductive types. - For co-inductive types, the only elimination principle is case analysis. - - This command supports the :attr:`universes(polymorphic)`, - :attr:`universes(monomorphic)`, :attr:`universes(template)`, - :attr:`universes(notemplate)`, :attr:`universes(cumulative)`, - :attr:`universes(noncumulative)` and :attr:`private(matching)` - attributes. - -.. example:: - - The type of infinite sequences of natural numbers, usually called streams, - is an example of a co-inductive type. - - .. coqtop:: in - - CoInductive Stream : Set := Seq : nat -> Stream -> Stream. - - The usual destructors on streams :g:`hd:Stream->nat` and :g:`tl:Str->Str` - can be defined as follows: - - .. coqtop:: in - - Definition hd (x:Stream) := let (a,s) := x in a. - Definition tl (x:Stream) := let (a,s) := x in s. - -Definitions of co-inductive predicates and blocks of mutually -co-inductive definitions are also allowed. - -.. example:: - - The extensional equality on streams is an example of a co-inductive type: - - .. coqtop:: in - - CoInductive EqSt : Stream -> Stream -> Prop := - eqst : forall s1 s2:Stream, - hd s1 = hd s2 -> EqSt (tl s1) (tl s2) -> EqSt s1 s2. - - In order to prove the extensional equality of two streams :g:`s1` and :g:`s2` - we have to construct an infinite proof of equality, that is, an infinite - object of type :g:`(EqSt s1 s2)`. We will see how to introduce infinite - objects in Section :ref:`cofixpoint`. - -Caveat -~~~~~~ - -The ability to define co-inductive types by constructors, hereafter called -*positive co-inductive types*, is known to break subject reduction. The story is -a bit long: this is due to dependent pattern-matching which implies -propositional η-equality, which itself would require full η-conversion for -subject reduction to hold, but full η-conversion is not acceptable as it would -make type checking undecidable. - -Since the introduction of primitive records in Coq 8.5, an alternative -presentation is available, called *negative co-inductive types*. This consists -in defining a co-inductive type as a primitive record type through its -projections. Such a technique is akin to the *co-pattern* style that can be -found in e.g. Agda, and preserves subject reduction. - -The above example can be rewritten in the following way. - -.. coqtop:: none - - Reset Stream. - -.. coqtop:: all - - Set Primitive Projections. - CoInductive Stream : Set := Seq { hd : nat; tl : Stream }. - CoInductive EqSt (s1 s2: Stream) : Prop := eqst { - eqst_hd : hd s1 = hd s2; - eqst_tl : EqSt (tl s1) (tl s2); - }. - -Some properties that hold over positive streams are lost when going to the -negative presentation, typically when they imply equality over streams. -For instance, propositional η-equality is lost when going to the negative -presentation. It is nonetheless logically consistent to recover it through an -axiom. - -.. coqtop:: all - - Axiom Stream_eta : forall s: Stream, s = Seq (hd s) (tl s). - -More generally, as in the case of positive coinductive types, it is consistent -to further identify extensional equality of coinductive types with propositional -equality: - -.. coqtop:: all - - Axiom Stream_ext : forall (s1 s2: Stream), EqSt s1 s2 -> s1 = s2. - -As of Coq 8.9, it is now advised to use negative co-inductive types rather than -their positive counterparts. - -.. seealso:: - :ref:`primitive_projections` for more information about negative - records and primitive projections. - - -Definition of recursive functions ---------------------------------- +.. _Fixpoint: -Definition of functions by recursion over inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Top-level recursive functions +----------------------------- This section describes the primitive form of definition by recursion over inductive objects. See the :cmd:`Function` command for more advanced constructions. -.. _Fixpoint: - .. cmd:: Fixpoint @fix_definition {* with @fix_definition } .. insertprodn fix_definition fix_definition @@ -1250,203 +172,3 @@ constructions. | leaf b => 1 | cons t f' => (tree_size t + forest_size f') end. - -.. _cofixpoint: - -Definitions of recursive objects in co-inductive types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. cmd:: CoFixpoint @cofix_definition {* with @cofix_definition } - - .. insertprodn cofix_definition cofix_definition - - .. prodn:: - cofix_definition ::= @ident_decl {* @binder } {? : @type } {? := @term } {? @decl_notations } - - This command introduces a method for constructing an infinite object of a - coinductive type. For example, the stream containing all natural numbers can - be introduced applying the following method to the number :g:`O` (see - Section :ref:`coinductive-types` for the definition of :g:`Stream`, :g:`hd` - and :g:`tl`): - - .. coqtop:: all - - CoFixpoint from (n:nat) : Stream := Seq n (from (S n)). - - Unlike recursive definitions, there is no decreasing argument in a - co-recursive definition. To be admissible, a method of construction must - provide at least one extra constructor of the infinite object for each - iteration. A syntactical guard condition is imposed on co-recursive - definitions in order to ensure this: each recursive call in the - definition must be protected by at least one constructor, and only by - constructors. That is the case in the former definition, where the single - recursive call of :g:`from` is guarded by an application of :g:`Seq`. - On the contrary, the following recursive function does not satisfy the - guard condition: - - .. coqtop:: all - - Fail CoFixpoint filter (p:nat -> bool) (s:Stream) : Stream := - if p (hd s) then Seq (hd s) (filter p (tl s)) else filter p (tl s). - - The elimination of co-recursive definition is done lazily, i.e. the - definition is expanded only when it occurs at the head of an application - which is the argument of a case analysis expression. In any other - context, it is considered as a canonical expression which is completely - evaluated. We can test this using the command :cmd:`Eval`, which computes - the normal forms of a term: - - .. coqtop:: all - - Eval compute in (from 0). - Eval compute in (hd (from 0)). - Eval compute in (tl (from 0)). - - As in the :cmd:`Fixpoint` command, the :n:`with` clause allows simultaneously - defining several mutual cofixpoints. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - -.. _Computations: - -Computations ------------- - -.. insertprodn reduce pattern_occ - -.. prodn:: - reduce ::= Eval @red_expr in - red_expr ::= red - | hnf - | simpl {? @delta_flag } {? @ref_or_pattern_occ } - | cbv {? @strategy_flag } - | cbn {? @strategy_flag } - | lazy {? @strategy_flag } - | compute {? @delta_flag } - | vm_compute {? @ref_or_pattern_occ } - | native_compute {? @ref_or_pattern_occ } - | unfold {+, @unfold_occ } - | fold {+ @one_term } - | pattern {+, @pattern_occ } - | @ident - delta_flag ::= {? - } [ {+ @smart_qualid } ] - strategy_flag ::= {+ @red_flags } - | @delta_flag - red_flags ::= beta - | iota - | match - | fix - | cofix - | zeta - | delta {? @delta_flag } - ref_or_pattern_occ ::= @smart_qualid {? at @occs_nums } - | @one_term {? at @occs_nums } - occs_nums ::= {+ {| @num | @ident } } - | - {| @num | @ident } {* @int_or_var } - int_or_var ::= @int - | @ident - unfold_occ ::= @smart_qualid {? at @occs_nums } - pattern_occ ::= @one_term {? at @occs_nums } - -See :ref:`Conversion-rules`. - -.. todo:: Add text here - -.. _Assertions: - -Assertions and proofs ---------------------- - -An assertion states a proposition (or a type) of which the proof (or an -inhabitant of the type) is interactively built using tactics. The interactive -proof mode is described in Chapter :ref:`proofhandling` and the tactics in -Chapter :ref:`Tactics`. The basic assertion command is: - -.. cmd:: @thm_token @ident_decl {* @binder } : @type {* with @ident_decl {* @binder } : @type } - :name: Theorem; Lemma; Fact; Remark; Corollary; Proposition; Property - - .. insertprodn thm_token thm_token - - .. prodn:: - thm_token ::= Theorem - | Lemma - | Fact - | Remark - | Corollary - | Proposition - | Property - - After the statement is asserted, Coq needs a proof. Once a proof of - :n:`@type` under the assumptions represented by :n:`@binder`\s is given and - validated, the proof is generalized into a proof of :n:`forall {* @binder }, @type` and - the theorem is bound to the name :n:`@ident` in the environment. - - Forms using the :n:`with` clause are useful for theorems that are proved by simultaneous induction - over a mutually inductive assumption, or that assert mutually dependent - statements in some mutual co-inductive type. It is equivalent to - :cmd:`Fixpoint` or :cmd:`CoFixpoint` but using tactics to build the proof of - the statements (or the body of the specification, depending on the point of - view). The inductive or co-inductive types on which the induction or - coinduction has to be done is assumed to be non ambiguous and is guessed by - the system. - - Like in a :cmd:`Fixpoint` or :cmd:`CoFixpoint` definition, the induction hypotheses - have to be used on *structurally smaller* arguments (for a :cmd:`Fixpoint`) or - be *guarded by a constructor* (for a :cmd:`CoFixpoint`). The verification that - recursive proof arguments are correct is done only at the time of registering - the lemma in the environment. To know if the use of induction hypotheses is - correct at some time of the interactive development of a proof, use the - command :cmd:`Guarded`. - - .. exn:: The term @term has type @type which should be Set, Prop or Type. - :undocumented: - - .. exn:: @ident already exists. - :name: @ident already exists. (Theorem) - - The name you provided is already defined. You have then to choose - another name. - - .. exn:: Nested proofs are not allowed unless you turn the Nested Proofs Allowed flag on. - - You are asserting a new statement while already being in proof editing mode. - This feature, called nested proofs, is disabled by default. - To activate it, turn the :flag:`Nested Proofs Allowed` flag on. - -Proofs start with the keyword :cmd:`Proof`. Then Coq enters the proof editing mode -until the proof is completed. In proof editing mode, the user primarily enters -tactics, which are described in chapter :ref:`Tactics`. The user may also enter -commands to manage the proof editing mode. They are described in Chapter -:ref:`proofhandling`. - -When the proof is complete, use the :cmd:`Qed` command so the kernel verifies -the proof and adds it to the environment. - -.. note:: - - #. Several statements can be simultaneously asserted provided the - :flag:`Nested Proofs Allowed` flag was turned on. - - #. Not only other assertions but any vernacular command can be given - while in the process of proving a given assertion. In this case, the - command is understood as if it would have been given before the - statements still to be proved. Nonetheless, this practice is discouraged - and may stop working in future versions. - - #. Proofs ended by :cmd:`Qed` are declared opaque. Their content cannot be - unfolded (see :ref:`performingcomputations`), thus - realizing some form of *proof-irrelevance*. To be able to unfold a - proof, the proof should be ended by :cmd:`Defined`. - - #. :cmd:`Proof` is recommended but can currently be omitted. On the opposite - side, :cmd:`Qed` (or :cmd:`Defined`) is mandatory to validate a proof. - - #. One can also use :cmd:`Admitted` in place of :cmd:`Qed` to turn the - current asserted statement into an axiom and exit the proof editing mode. - -.. [1] - Except if the inductive type is empty in which case there is no - equation that can be used to infer the return type. -- cgit v1.2.3 From 1d34b15750ae16bf2c3b5291d0b507ec9c2e8c23 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 20:07:12 +0200 Subject: Add Recursive functions to new file on Inductive types. --- doc/sphinx/language/core/inductive.rst | 174 +++++++++++++++++++++ .../language/gallina-specification-language.rst | 174 --------------------- 2 files changed, 174 insertions(+), 174 deletions(-) create mode 100644 doc/sphinx/language/core/inductive.rst delete mode 100644 doc/sphinx/language/gallina-specification-language.rst diff --git a/doc/sphinx/language/core/inductive.rst b/doc/sphinx/language/core/inductive.rst new file mode 100644 index 0000000000..6e5417535a --- /dev/null +++ b/doc/sphinx/language/core/inductive.rst @@ -0,0 +1,174 @@ +.. index:: + single: fix + +Recursive functions: fix +------------------------ + +.. insertprodn term_fix fixannot + +.. prodn:: + term_fix ::= let fix @fix_body in @term + | fix @fix_body {? {+ with @fix_body } for @ident } + fix_body ::= @ident {* @binder } {? @fixannot } {? : @type } := @term + fixannot ::= %{ struct @ident %} + | %{ wf @one_term @ident %} + | %{ measure @one_term {? @ident } {? @one_term } %} + + +The expression ":n:`fix @ident__1 @binder__1 : @type__1 := @term__1 with … with @ident__n @binder__n : @type__n := @term__n for @ident__i`" denotes the +:math:`i`-th component of a block of functions defined by mutual structural +recursion. It is the local counterpart of the :cmd:`Fixpoint` command. When +:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. + +The association of a single fixpoint and a local definition have a special +syntax: :n:`let fix @ident {* @binder } := @term in` stands for +:n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for co-fixpoints. + +Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` +only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in +commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. + +.. _Fixpoint: + +Top-level recursive functions +----------------------------- + +This section describes the primitive form of definition by recursion over +inductive objects. See the :cmd:`Function` command for more advanced +constructions. + +.. cmd:: Fixpoint @fix_definition {* with @fix_definition } + + .. insertprodn fix_definition fix_definition + + .. prodn:: + fix_definition ::= @ident_decl {* @binder } {? @fixannot } {? : @type } {? := @term } {? @decl_notations } + + This command allows defining functions by pattern matching over inductive + objects using a fixed point construction. The meaning of this declaration is + to define :n:`@ident` as a recursive function with arguments specified by + the :n:`@binder`\s such that :n:`@ident` applied to arguments + corresponding to these :n:`@binder`\s has type :n:`@type`, and is + equivalent to the expression :n:`@term`. The type of :n:`@ident` is + consequently :n:`forall {* @binder }, @type` and its value is equivalent + to :n:`fun {* @binder } => @term`. + + To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical + constraints on a special argument called the decreasing argument. They + are needed to ensure that the :cmd:`Fixpoint` definition always terminates. + The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to + let the user tell the system which argument decreases along the recursive calls. + + The :n:`{struct @ident}` annotation may be left implicit, in which case the + system successively tries arguments from left to right until it finds one + that satisfies the decreasing condition. + + :cmd:`Fixpoint` without the :attr:`program` attribute does not support the + :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. + + The :n:`with` clause allows simultaneously defining several mutual fixpoints. + It is especially useful when defining functions over mutually defined + inductive types. Example: :ref:`Mutual Fixpoints`. + + If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. + This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. + In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant + for which the computational behavior is relevant. See :ref:`proof-editing-mode`. + + .. note:: + + + Some fixpoints may have several arguments that fit as decreasing + arguments, and this choice influences the reduction of the fixpoint. + Hence an explicit annotation must be used if the leftmost decreasing + argument is not the desired one. Writing explicit annotations can also + speed up type checking of large mutual fixpoints. + + + In order to keep the strong normalization property, the fixed point + reduction will only be performed when the argument in position of the + decreasing argument (which type should be in an inductive definition) + starts with a constructor. + + + .. example:: + + One can define the addition function as : + + .. coqtop:: all + + Fixpoint add (n m:nat) {struct n} : nat := + match n with + | O => m + | S p => S (add p m) + end. + + The match operator matches a value (here :g:`n`) with the various + constructors of its (inductive) type. The remaining arguments give the + respective values to be returned, as functions of the parameters of the + corresponding constructor. Thus here when :g:`n` equals :g:`O` we return + :g:`m`, and when :g:`n` equals :g:`(S p)` we return :g:`(S (add p m))`. + + The match operator is formally described in + Section :ref:`match-construction`. + The system recognizes that in the inductive call :g:`(add p m)` the first + argument actually decreases because it is a *pattern variable* coming + from :g:`match n with`. + + .. example:: + + The following definition is not correct and generates an error message: + + .. coqtop:: all + + Fail Fixpoint wrongplus (n m:nat) {struct n} : nat := + match m with + | O => n + | S p => S (wrongplus n p) + end. + + because the declared decreasing argument :g:`n` does not actually + decrease in the recursive call. The function computing the addition over + the second argument should rather be written: + + .. coqtop:: all + + Fixpoint plus (n m:nat) {struct m} : nat := + match m with + | O => n + | S p => S (plus n p) + end. + + .. example:: + + The recursive call may not only be on direct subterms of the recursive + variable :g:`n` but also on a deeper subterm and we can directly write + the function :g:`mod2` which gives the remainder modulo 2 of a natural + number. + + .. coqtop:: all + + Fixpoint mod2 (n:nat) : nat := + match n with + | O => O + | S p => match p with + | O => S O + | S q => mod2 q + end + end. + +.. _example_mutual_fixpoints: + + .. example:: Mutual fixpoints + + The size of trees and forests can be defined the following way: + + .. coqtop:: all + + Fixpoint tree_size (t:tree) : nat := + match t with + | node a f => S (forest_size f) + end + with forest_size (f:forest) : nat := + match f with + | leaf b => 1 + | cons t f' => (tree_size t + forest_size f') + end. diff --git a/doc/sphinx/language/gallina-specification-language.rst b/doc/sphinx/language/gallina-specification-language.rst deleted file mode 100644 index 6e5417535a..0000000000 --- a/doc/sphinx/language/gallina-specification-language.rst +++ /dev/null @@ -1,174 +0,0 @@ -.. index:: - single: fix - -Recursive functions: fix ------------------------- - -.. insertprodn term_fix fixannot - -.. prodn:: - term_fix ::= let fix @fix_body in @term - | fix @fix_body {? {+ with @fix_body } for @ident } - fix_body ::= @ident {* @binder } {? @fixannot } {? : @type } := @term - fixannot ::= %{ struct @ident %} - | %{ wf @one_term @ident %} - | %{ measure @one_term {? @ident } {? @one_term } %} - - -The expression ":n:`fix @ident__1 @binder__1 : @type__1 := @term__1 with … with @ident__n @binder__n : @type__n := @term__n for @ident__i`" denotes the -:math:`i`-th component of a block of functions defined by mutual structural -recursion. It is the local counterpart of the :cmd:`Fixpoint` command. When -:math:`n=1`, the ":n:`for @ident__i`" clause is omitted. - -The association of a single fixpoint and a local definition have a special -syntax: :n:`let fix @ident {* @binder } := @term in` stands for -:n:`let @ident := fix @ident {* @binder } := @term in`. The same applies for co-fixpoints. - -Some options of :n:`@fixannot` are only supported in specific constructs. :n:`fix` and :n:`let fix` -only support the :n:`struct` option, while :n:`wf` and :n:`measure` are only supported in -commands such as :cmd:`Function` and :cmd:`Program Fixpoint`. - -.. _Fixpoint: - -Top-level recursive functions ------------------------------ - -This section describes the primitive form of definition by recursion over -inductive objects. See the :cmd:`Function` command for more advanced -constructions. - -.. cmd:: Fixpoint @fix_definition {* with @fix_definition } - - .. insertprodn fix_definition fix_definition - - .. prodn:: - fix_definition ::= @ident_decl {* @binder } {? @fixannot } {? : @type } {? := @term } {? @decl_notations } - - This command allows defining functions by pattern matching over inductive - objects using a fixed point construction. The meaning of this declaration is - to define :n:`@ident` as a recursive function with arguments specified by - the :n:`@binder`\s such that :n:`@ident` applied to arguments - corresponding to these :n:`@binder`\s has type :n:`@type`, and is - equivalent to the expression :n:`@term`. The type of :n:`@ident` is - consequently :n:`forall {* @binder }, @type` and its value is equivalent - to :n:`fun {* @binder } => @term`. - - To be accepted, a :cmd:`Fixpoint` definition has to satisfy syntactical - constraints on a special argument called the decreasing argument. They - are needed to ensure that the :cmd:`Fixpoint` definition always terminates. - The point of the :n:`{struct @ident}` annotation (see :n:`@fixannot`) is to - let the user tell the system which argument decreases along the recursive calls. - - The :n:`{struct @ident}` annotation may be left implicit, in which case the - system successively tries arguments from left to right until it finds one - that satisfies the decreasing condition. - - :cmd:`Fixpoint` without the :attr:`program` attribute does not support the - :n:`wf` or :n:`measure` clauses of :n:`@fixannot`. - - The :n:`with` clause allows simultaneously defining several mutual fixpoints. - It is especially useful when defining functions over mutually defined - inductive types. Example: :ref:`Mutual Fixpoints`. - - If :n:`@term` is omitted, :n:`@type` is required and Coq enters proof editing mode. - This can be used to define a term incrementally, in particular by relying on the :tacn:`refine` tactic. - In this case, the proof should be terminated with :cmd:`Defined` in order to define a constant - for which the computational behavior is relevant. See :ref:`proof-editing-mode`. - - .. note:: - - + Some fixpoints may have several arguments that fit as decreasing - arguments, and this choice influences the reduction of the fixpoint. - Hence an explicit annotation must be used if the leftmost decreasing - argument is not the desired one. Writing explicit annotations can also - speed up type checking of large mutual fixpoints. - - + In order to keep the strong normalization property, the fixed point - reduction will only be performed when the argument in position of the - decreasing argument (which type should be in an inductive definition) - starts with a constructor. - - - .. example:: - - One can define the addition function as : - - .. coqtop:: all - - Fixpoint add (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (add p m) - end. - - The match operator matches a value (here :g:`n`) with the various - constructors of its (inductive) type. The remaining arguments give the - respective values to be returned, as functions of the parameters of the - corresponding constructor. Thus here when :g:`n` equals :g:`O` we return - :g:`m`, and when :g:`n` equals :g:`(S p)` we return :g:`(S (add p m))`. - - The match operator is formally described in - Section :ref:`match-construction`. - The system recognizes that in the inductive call :g:`(add p m)` the first - argument actually decreases because it is a *pattern variable* coming - from :g:`match n with`. - - .. example:: - - The following definition is not correct and generates an error message: - - .. coqtop:: all - - Fail Fixpoint wrongplus (n m:nat) {struct n} : nat := - match m with - | O => n - | S p => S (wrongplus n p) - end. - - because the declared decreasing argument :g:`n` does not actually - decrease in the recursive call. The function computing the addition over - the second argument should rather be written: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct m} : nat := - match m with - | O => n - | S p => S (plus n p) - end. - - .. example:: - - The recursive call may not only be on direct subterms of the recursive - variable :g:`n` but also on a deeper subterm and we can directly write - the function :g:`mod2` which gives the remainder modulo 2 of a natural - number. - - .. coqtop:: all - - Fixpoint mod2 (n:nat) : nat := - match n with - | O => O - | S p => match p with - | O => S O - | S q => mod2 q - end - end. - -.. _example_mutual_fixpoints: - - .. example:: Mutual fixpoints - - The size of trees and forests can be defined the following way: - - .. coqtop:: all - - Fixpoint tree_size (t:tree) : nat := - match t with - | node a f => S (forest_size f) - end - with forest_size (f:forest) : nat := - match f with - | leaf b => 1 - | cons t f' => (tree_size t + forest_size f') - end. -- cgit v1.2.3 From 485c5a1590daaee61a4ca7801fd6de3ee7489e6c Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 20:10:14 +0200 Subject: Extract Inductive types from CIC. --- doc/sphinx/language/cic.rst | 894 -------------------------------------------- 1 file changed, 894 deletions(-) diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst index b125d21a3c..678374e83e 100644 --- a/doc/sphinx/language/cic.rst +++ b/doc/sphinx/language/cic.rst @@ -1,734 +1,3 @@ -.. _calculusofinductiveconstructions: - - -Calculus of Inductive Constructions -==================================== - -The underlying formal language of |Coq| is a *Calculus of Inductive -Constructions* (|Cic|) whose inference rules are presented in this -chapter. The history of this formalism as well as pointers to related -work are provided in a separate chapter; see *Credits*. - - -.. _The-terms: - -The terms -------------- - -The expressions of the |Cic| are *terms* and all terms have a *type*. -There are types for functions (or programs), there are atomic types -(especially datatypes)... but also types for proofs and types for the -types themselves. Especially, any object handled in the formalism must -belong to a type. For instance, universal quantification is relative -to a type and takes the form “*for all x of type* :math:`T`, :math:`P`”. The expression -“:math:`x` *of type* :math:`T`” is written “:math:`x:T`”. Informally, “:math:`x:T`” can be thought as -“:math:`x` *belongs to* :math:`T`”. - -The types of types are called :gdef:`sort`\s. Types and sorts are themselves terms -so that terms, types and sorts are all components of a common -syntactic language of terms which is described in Section :ref:`terms`. But -first, we describe sorts. - - -.. _Sorts: - -Sorts -~~~~~~~~~~~ - -All sorts have a type and there is an infinite well-founded typing -hierarchy of sorts whose base sorts are :math:`\SProp`, :math:`\Prop` -and :math:`\Set`. - -The sort :math:`\Prop` intends to be the type of logical propositions. If :math:`M` is a -logical proposition then it denotes the class of terms representing -proofs of :math:`M`. An object :math:`m` belonging to :math:`M` witnesses the fact that :math:`M` is -provable. An object of type :math:`\Prop` is called a proposition. - -The sort :math:`\SProp` is like :math:`\Prop` but the propositions in -:math:`\SProp` are known to have irrelevant proofs (all proofs are -equal). Objects of type :math:`\SProp` are called strict propositions. -See :ref:`sprop` for information about using -:math:`\SProp`, and :cite:`Gilbert:POPL2019` for meta theoretical -considerations. - -The sort :math:`\Set` intends to be the type of small sets. This includes data -types such as booleans and naturals, but also products, subsets, and -function types over these data types. - -:math:`\SProp`, :math:`\Prop` and :math:`\Set` themselves can be manipulated as ordinary terms. -Consequently they also have a type. Because assuming simply that :math:`\Set` -has type :math:`\Set` leads to an inconsistent theory :cite:`Coq86`, the language of -|Cic| has infinitely many sorts. There are, in addition to the base sorts, -a hierarchy of universes :math:`\Type(i)` for any integer :math:`i ≥ 1`. - -Like :math:`\Set`, all of the sorts :math:`\Type(i)` contain small sets such as -booleans, natural numbers, as well as products, subsets and function -types over small sets. But, unlike :math:`\Set`, they also contain large sets, -namely the sorts :math:`\Set` and :math:`\Type(j)` for :math:`j u` - in |Coq| concrete syntax) is a term. This is a notation for the - λ-abstraction of λ-calculus :cite:`Bar81`. The term :math:`λ x:T .~u` is a function - which maps elements of :math:`T` to the expression :math:`u`. -#. if :math:`t` and :math:`u` are terms then :math:`(t~u)` is a term - (:g:`t u` in |Coq| concrete - syntax). The term :math:`(t~u)` reads as “:math:`t` applied to :math:`u`”. -#. if :math:`x` is a variable, and :math:`t`, :math:`T` and :math:`u` are - terms then :math:`\letin{x}{t:T}{u}` is - a term which denotes the term :math:`u` where the variable :math:`x` is locally bound - to :math:`t` of type :math:`T`. This stands for the common “let-in” construction of - functional programs such as ML or Scheme. - - - -.. _Free-variables: - -**Free variables.** -The notion of free variables is defined as usual. In the expressions -:math:`λx:T.~U` and :math:`∀ x:T,~U` the occurrences of :math:`x` in :math:`U` are bound. - - -.. _Substitution: - -**Substitution.** -The notion of substituting a term :math:`t` to free occurrences of a variable -:math:`x` in a term :math:`u` is defined as usual. The resulting term is written -:math:`\subst{u}{x}{t}`. - - -.. _The-logical-vs-programming-readings: - -**The logical vs programming readings.** -The constructions of the |Cic| can be used to express both logical and -programming notions, accordingly to the Curry-Howard correspondence -between proofs and programs, and between propositions and types -:cite:`Cur58,How80,Bru72`. - -For instance, let us assume that :math:`\nat` is the type of natural numbers -with zero element written :math:`0` and that :g:`True` is the always true -proposition. Then :math:`→` is used both to denote :math:`\nat→\nat` which is the type -of functions from :math:`\nat` to :math:`\nat`, to denote True→True which is an -implicative proposition, to denote :math:`\nat →\Prop` which is the type of -unary predicates over the natural numbers, etc. - -Let us assume that ``mult`` is a function of type :math:`\nat→\nat→\nat` and ``eqnat`` a -predicate of type :math:`\nat→\nat→ \Prop`. The λ-abstraction can serve to build -“ordinary” functions as in :math:`λ x:\nat.~(\kw{mult}~x~x)` (i.e. -:g:`fun x:nat => mult x x` -in |Coq| notation) but may build also predicates over the natural -numbers. For instance :math:`λ x:\nat.~(\kw{eqnat}~x~0)` -(i.e. :g:`fun x:nat => eqnat x 0` -in |Coq| notation) will represent the predicate of one variable :math:`x` which -asserts the equality of :math:`x` with :math:`0`. This predicate has type -:math:`\nat → \Prop` -and it can be applied to any expression of type :math:`\nat`, say :math:`t`, to give an -object :math:`P~t` of type :math:`\Prop`, namely a proposition. - -Furthermore :g:`forall x:nat, P x` will represent the type of functions -which associate to each natural number :math:`n` an object of type :math:`(P~n)` and -consequently represent the type of proofs of the formula “:math:`∀ x.~P(x)`”. - - -.. _Typing-rules: - -Typing rules ----------------- - -As objects of type theory, terms are subjected to *type discipline*. -The well typing of a term depends on a global environment and a local -context. - - -.. _Local-context: - -**Local context.** -A *local context* is an ordered list of *local declarations* of names -which we call *variables*. The declaration of some variable :math:`x` is -either a *local assumption*, written :math:`x:T` (:math:`T` is a type) or a *local -definition*, written :math:`x:=t:T`. We use brackets to write local contexts. -A typical example is :math:`[x:T;~y:=u:U;~z:V]`. Notice that the variables -declared in a local context must be distinct. If :math:`Γ` is a local context -that declares some :math:`x`, we -write :math:`x ∈ Γ`. By writing :math:`(x:T) ∈ Γ` we mean that either :math:`x:T` is an -assumption in :math:`Γ` or that there exists some :math:`t` such that :math:`x:=t:T` is a -definition in :math:`Γ`. If :math:`Γ` defines some :math:`x:=t:T`, we also write :math:`(x:=t:T) ∈ Γ`. -For the rest of the chapter, :math:`Γ::(y:T)` denotes the local context :math:`Γ` -enriched with the local assumption :math:`y:T`. Similarly, :math:`Γ::(y:=t:T)` denotes -the local context :math:`Γ` enriched with the local definition :math:`(y:=t:T)`. The -notation :math:`[]` denotes the empty local context. By :math:`Γ_1 ; Γ_2` we mean -concatenation of the local context :math:`Γ_1` and the local context :math:`Γ_2`. - - -.. _Global-environment: - -**Global environment.** -A *global environment* is an ordered list of *global declarations*. -Global declarations are either *global assumptions* or *global -definitions*, but also declarations of inductive objects. Inductive -objects themselves declare both inductive or coinductive types and -constructors (see Section :ref:`inductive-definitions`). - -A *global assumption* will be represented in the global environment as -:math:`(c:T)` which assumes the name :math:`c` to be of some type :math:`T`. A *global -definition* will be represented in the global environment as :math:`c:=t:T` -which defines the name :math:`c` to have value :math:`t` and type :math:`T`. We shall call -such names *constants*. For the rest of the chapter, the :math:`E;~c:T` denotes -the global environment :math:`E` enriched with the global assumption :math:`c:T`. -Similarly, :math:`E;~c:=t:T` denotes the global environment :math:`E` enriched with the -global definition :math:`(c:=t:T)`. - -The rules for inductive definitions (see Section -:ref:`inductive-definitions`) have to be considered as assumption -rules to which the following definitions apply: if the name :math:`c` -is declared in :math:`E`, we write :math:`c ∈ E` and if :math:`c:T` or -:math:`c:=t:T` is declared in :math:`E`, we write :math:`(c : T) ∈ E`. - - -.. _Typing-rules2: - -**Typing rules.** -In the following, we define simultaneously two judgments. The first -one :math:`\WTEG{t}{T}` means the term :math:`t` is well-typed and has type :math:`T` in the -global environment :math:`E` and local context :math:`Γ`. The second judgment :math:`\WFE{Γ}` -means that the global environment :math:`E` is well-formed and the local -context :math:`Γ` is a valid local context in this global environment. - -A term :math:`t` is well typed in a global environment :math:`E` iff -there exists a local context :math:`\Gamma` and a term :math:`T` such -that the judgment :math:`\WTEG{t}{T}` can be derived from the -following rules. - -.. inference:: W-Empty - - --------- - \WF{[]}{} - -.. inference:: W-Local-Assum - - \WTEG{T}{s} - s \in \Sort - x \not\in \Gamma % \cup E - ------------------------- - \WFE{\Gamma::(x:T)} - -.. inference:: W-Local-Def - - \WTEG{t}{T} - x \not\in \Gamma % \cup E - ------------------------- - \WFE{\Gamma::(x:=t:T)} - -.. inference:: W-Global-Assum - - \WTE{}{T}{s} - s \in \Sort - c \notin E - ------------ - \WF{E;~c:T}{} - -.. inference:: W-Global-Def - - \WTE{}{t}{T} - c \notin E - --------------- - \WF{E;~c:=t:T}{} - -.. inference:: Ax-SProp - - \WFE{\Gamma} - ---------------------- - \WTEG{\SProp}{\Type(1)} - -.. inference:: Ax-Prop - - \WFE{\Gamma} - ---------------------- - \WTEG{\Prop}{\Type(1)} - -.. inference:: Ax-Set - - \WFE{\Gamma} - --------------------- - \WTEG{\Set}{\Type(1)} - -.. inference:: Ax-Type - - \WFE{\Gamma} - --------------------------- - \WTEG{\Type(i)}{\Type(i+1)} - -.. inference:: Var - - \WFE{\Gamma} - (x:T) \in \Gamma~~\mbox{or}~~(x:=t:T) \in \Gamma~\mbox{for some $t$} - -------------------------------------------------------------------- - \WTEG{x}{T} - -.. inference:: Const - - \WFE{\Gamma} - (c:T) \in E~~\mbox{or}~~(c:=t:T) \in E~\mbox{for some $t$} - ---------------------------------------------------------- - \WTEG{c}{T} - -.. inference:: Prod-SProp - - \WTEG{T}{s} - s \in {\Sort} - \WTE{\Gamma::(x:T)}{U}{\SProp} - ----------------------------- - \WTEG{\forall~x:T,U}{\SProp} - -.. inference:: Prod-Prop - - \WTEG{T}{s} - s \in \Sort - \WTE{\Gamma::(x:T)}{U}{\Prop} - ----------------------------- - \WTEG{∀ x:T,~U}{\Prop} - -.. inference:: Prod-Set - - \WTEG{T}{s} - s \in \{\SProp, \Prop, \Set\} - \WTE{\Gamma::(x:T)}{U}{\Set} - ---------------------------- - \WTEG{∀ x:T,~U}{\Set} - -.. inference:: Prod-Type - - \WTEG{T}{s} - s \in \{\SProp, \Type{i}\} - \WTE{\Gamma::(x:T)}{U}{\Type(i)} - -------------------------------- - \WTEG{∀ x:T,~U}{\Type(i)} - -.. inference:: Lam - - \WTEG{∀ x:T,~U}{s} - \WTE{\Gamma::(x:T)}{t}{U} - ------------------------------------ - \WTEG{λ x:T\mto t}{∀ x:T,~U} - -.. inference:: App - - \WTEG{t}{∀ x:U,~T} - \WTEG{u}{U} - ------------------------------ - \WTEG{(t\ u)}{\subst{T}{x}{u}} - -.. inference:: Let - - \WTEG{t}{T} - \WTE{\Gamma::(x:=t:T)}{u}{U} - ----------------------------------------- - \WTEG{\letin{x}{t:T}{u}}{\subst{U}{x}{t}} - - - -.. note:: - - **Prod-Prop** and **Prod-Set** typing-rules make sense if we consider the - semantic difference between :math:`\Prop` and :math:`\Set`: - - + All values of a type that has a sort :math:`\Set` are extractable. - + No values of a type that has a sort :math:`\Prop` are extractable. - - - -.. note:: - We may have :math:`\letin{x}{t:T}{u}` well-typed without having - :math:`((λ x:T.~u)~t)` well-typed (where :math:`T` is a type of - :math:`t`). This is because the value :math:`t` associated to - :math:`x` may be used in a conversion rule - (see Section :ref:`Conversion-rules`). - - -.. _Conversion-rules: - -Conversion rules --------------------- - -In |Cic|, there is an internal reduction mechanism. In particular, it -can decide if two programs are *intentionally* equal (one says -*convertible*). Convertibility is described in this section. - - -.. _beta-reduction: - -β-reduction -~~~~~~~~~~~ - -We want to be able to identify some terms as we can identify the -application of a function to a given argument with its result. For -instance the identity function over a given type :math:`T` can be written -:math:`λx:T.~x`. In any global environment :math:`E` and local context -:math:`Γ`, we want to identify any object :math:`a` (of type -:math:`T`) with the application :math:`((λ x:T.~x)~a)`. We define for -this a *reduction* (or a *conversion*) rule we call :math:`β`: - -.. math:: - - E[Γ] ⊢ ((λx:T.~t)~u)~\triangleright_β~\subst{t}{x}{u} - -We say that :math:`\subst{t}{x}{u}` is the *β-contraction* of -:math:`((λx:T.~t)~u)` and, conversely, that :math:`((λ x:T.~t)~u)` is the -*β-expansion* of :math:`\subst{t}{x}{u}`. - -According to β-reduction, terms of the *Calculus of Inductive -Constructions* enjoy some fundamental properties such as confluence, -strong normalization, subject reduction. These results are -theoretically of great importance but we will not detail them here and -refer the interested reader to :cite:`Coq85`. - - -.. _iota-reduction: - -ι-reduction -~~~~~~~~~~~ - -A specific conversion rule is associated to the inductive objects in -the global environment. We shall give later on (see Section -:ref:`Well-formed-inductive-definitions`) the precise rules but it -just says that a destructor applied to an object built from a -constructor behaves as expected. This reduction is called ι-reduction -and is more precisely studied in :cite:`Moh93,Wer94`. - - -.. _delta-reduction: - -δ-reduction -~~~~~~~~~~~ - -We may have variables defined in local contexts or constants defined -in the global environment. It is legal to identify such a reference -with its value, that is to expand (or unfold) it into its value. This -reduction is called δ-reduction and shows as follows. - -.. inference:: Delta-Local - - \WFE{\Gamma} - (x:=t:T) ∈ Γ - -------------- - E[Γ] ⊢ x~\triangleright_Δ~t - -.. inference:: Delta-Global - - \WFE{\Gamma} - (c:=t:T) ∈ E - -------------- - E[Γ] ⊢ c~\triangleright_δ~t - - -.. _zeta-reduction: - -ζ-reduction -~~~~~~~~~~~ - -|Coq| allows also to remove local definitions occurring in terms by -replacing the defined variable by its value. The declaration being -destroyed, this reduction differs from δ-reduction. It is called -ζ-reduction and shows as follows. - -.. inference:: Zeta - - \WFE{\Gamma} - \WTEG{u}{U} - \WTE{\Gamma::(x:=u:U)}{t}{T} - -------------- - E[Γ] ⊢ \letin{x}{u:U}{t}~\triangleright_ζ~\subst{t}{x}{u} - - -.. _eta-expansion: - -η-expansion -~~~~~~~~~~~ - -Another important concept is η-expansion. It is legal to identify any -term :math:`t` of functional type :math:`∀ x:T,~U` with its so-called η-expansion - -.. math:: - λx:T.~(t~x) - -for :math:`x` an arbitrary variable name fresh in :math:`t`. - - -.. note:: - - We deliberately do not define η-reduction: - - .. math:: - λ x:T.~(t~x)~\not\triangleright_η~t - - This is because, in general, the type of :math:`t` need not to be convertible - to the type of :math:`λ x:T.~(t~x)`. E.g., if we take :math:`f` such that: - - .. math:: - f ~:~ ∀ x:\Type(2),~\Type(1) - - then - - .. math:: - λ x:\Type(1).~(f~x) ~:~ ∀ x:\Type(1),~\Type(1) - - We could not allow - - .. math:: - λ x:\Type(1).~(f~x) ~\triangleright_η~ f - - because the type of the reduced term :math:`∀ x:\Type(2),~\Type(1)` would not be - convertible to the type of the original term :math:`∀ x:\Type(1),~\Type(1)`. - -.. _proof-irrelevance: - -Proof Irrelevance -~~~~~~~~~~~~~~~~~ - -It is legal to identify any two terms whose common type is a strict -proposition :math:`A : \SProp`. Terms in a strict propositions are -therefore called *irrelevant*. - -.. _convertibility: - -Convertibility -~~~~~~~~~~~~~~ - -Let us write :math:`E[Γ] ⊢ t \triangleright u` for the contextual closure of the -relation :math:`t` reduces to :math:`u` in the global environment -:math:`E` and local context :math:`Γ` with one of the previous -reductions β, δ, ι or ζ. - -We say that two terms :math:`t_1` and :math:`t_2` are -*βδιζη-convertible*, or simply *convertible*, or *equivalent*, in the -global environment :math:`E` and local context :math:`Γ` iff there -exist terms :math:`u_1` and :math:`u_2` such that :math:`E[Γ] ⊢ t_1 \triangleright -… \triangleright u_1` and :math:`E[Γ] ⊢ t_2 \triangleright … \triangleright u_2` and either :math:`u_1` and -:math:`u_2` are identical up to irrelevant subterms, or they are convertible up to η-expansion, -i.e. :math:`u_1` is :math:`λ x:T.~u_1'` and :math:`u_2 x` is -recursively convertible to :math:`u_1'`, or, symmetrically, -:math:`u_2` is :math:`λx:T.~u_2'` -and :math:`u_1 x` is recursively convertible to :math:`u_2'`. We then write -:math:`E[Γ] ⊢ t_1 =_{βδιζη} t_2`. - -Apart from this we consider two instances of polymorphic and -cumulative (see Chapter :ref:`polymorphicuniverses`) inductive types -(see below) convertible - -.. math:: - E[Γ] ⊢ t~w_1 … w_m =_{βδιζη} t~w_1' … w_m' - -if we have subtypings (see below) in both directions, i.e., - -.. math:: - E[Γ] ⊢ t~w_1 … w_m ≤_{βδιζη} t~w_1' … w_m' - -and - -.. math:: - E[Γ] ⊢ t~w_1' … w_m' ≤_{βδιζη} t~w_1 … w_m. - -Furthermore, we consider - -.. math:: - E[Γ] ⊢ c~v_1 … v_m =_{βδιζη} c'~v_1' … v_m' - -convertible if - -.. math:: - E[Γ] ⊢ v_i =_{βδιζη} v_i' - -and we have that :math:`c` and :math:`c'` -are the same constructors of different instances of the same inductive -types (differing only in universe levels) such that - -.. math:: - E[Γ] ⊢ c~v_1 … v_m : t~w_1 … w_m - -and - -.. math:: - E[Γ] ⊢ c'~v_1' … v_m' : t'~ w_1' … w_m ' - -and we have - -.. math:: - E[Γ] ⊢ t~w_1 … w_m =_{βδιζη} t~w_1' … w_m'. - -The convertibility relation allows introducing a new typing rule which -says that two convertible well-formed types have the same inhabitants. - - -.. _subtyping-rules: - -Subtyping rules -------------------- - -At the moment, we did not take into account one rule between universes -which says that any term in a universe of index :math:`i` is also a term in -the universe of index :math:`i+1` (this is the *cumulativity* rule of |Cic|). -This property extends the equivalence relation of convertibility into -a *subtyping* relation inductively defined by: - - -#. if :math:`E[Γ] ⊢ t =_{βδιζη} u` then :math:`E[Γ] ⊢ t ≤_{βδιζη} u`, -#. if :math:`i ≤ j` then :math:`E[Γ] ⊢ \Type(i) ≤_{βδιζη} \Type(j)`, -#. for any :math:`i`, :math:`E[Γ] ⊢ \Set ≤_{βδιζη} \Type(i)`, -#. :math:`E[Γ] ⊢ \Prop ≤_{βδιζη} \Set`, hence, by transitivity, - :math:`E[Γ] ⊢ \Prop ≤_{βδιζη} \Type(i)`, for any :math:`i` - (note: :math:`\SProp` is not related by cumulativity to any other term) -#. if :math:`E[Γ] ⊢ T =_{βδιζη} U` and - :math:`E[Γ::(x:T)] ⊢ T' ≤_{βδιζη} U'` then - :math:`E[Γ] ⊢ ∀x:T,~T′ ≤_{βδιζη} ∀ x:U,~U′`. -#. if :math:`\ind{p}{Γ_I}{Γ_C}` is a universe polymorphic and cumulative - (see Chapter :ref:`polymorphicuniverses`) inductive type (see below) - and - :math:`(t : ∀Γ_P ,∀Γ_{\mathit{Arr}(t)}, S)∈Γ_I` - and - :math:`(t' : ∀Γ_P' ,∀Γ_{\mathit{Arr}(t)}', S')∈Γ_I` - are two different instances of *the same* inductive type (differing only in - universe levels) with constructors - - .. math:: - [c_1 : ∀Γ_P ,∀ T_{1,1} … T_{1,n_1} ,~t~v_{1,1} … v_{1,m} ;~…;~ - c_k : ∀Γ_P ,∀ T_{k,1} … T_{k,n_k} ,~t~v_{k,1} … v_{k,m} ] - - and - - .. math:: - [c_1 : ∀Γ_P' ,∀ T_{1,1}' … T_{1,n_1}' ,~t'~v_{1,1}' … v_{1,m}' ;~…;~ - c_k : ∀Γ_P' ,∀ T_{k,1}' … T_{k,n_k}' ,~t'~v_{k,1}' … v_{k,m}' ] - - respectively then - - .. math:: - E[Γ] ⊢ t~w_1 … w_m ≤_{βδιζη} t'~w_1' … w_m' - - (notice that :math:`t` and :math:`t'` are both - fully applied, i.e., they have a sort as a type) if - - .. math:: - E[Γ] ⊢ w_i =_{βδιζη} w_i' - - for :math:`1 ≤ i ≤ m` and we have - - - .. math:: - E[Γ] ⊢ T_{i,j} ≤_{βδιζη} T_{i,j}' - - and - - .. math:: - E[Γ] ⊢ A_i ≤_{βδιζη} A_i' - - where :math:`Γ_{\mathit{Arr}(t)} = [a_1 : A_1 ;~ … ;~a_l : A_l ]` and - :math:`Γ_{\mathit{Arr}(t)}' = [a_1 : A_1';~ … ;~a_l : A_l']`. - - -The conversion rule up to subtyping is now exactly: - -.. inference:: Conv - - E[Γ] ⊢ U : s - E[Γ] ⊢ t : T - E[Γ] ⊢ T ≤_{βδιζη} U - -------------- - E[Γ] ⊢ t : U - - -.. _Normal-form: - -**Normal form**. A term which cannot be any more reduced is said to be in *normal -form*. There are several ways (or strategies) to apply the reduction -rules. Among them, we have to mention the *head reduction* which will -play an important role (see Chapter :ref:`tactics`). Any term :math:`t` can be written as -:math:`λ x_1 :T_1 .~… λ x_k :T_k .~(t_0~t_1 … t_n )` where :math:`t_0` is not an -application. We say then that :math:`t_0` is the *head of* :math:`t`. If we assume -that :math:`t_0` is :math:`λ x:T.~u_0` then one step of β-head reduction of :math:`t` is: - -.. math:: - λ x_1 :T_1 .~… λ x_k :T_k .~(λ x:T.~u_0~t_1 … t_n ) ~\triangleright~ - λ (x_1 :T_1 )…(x_k :T_k ).~(\subst{u_0}{x}{t_1}~t_2 … t_n ) - -Iterating the process of head reduction until the head of the reduced -term is no more an abstraction leads to the *β-head normal form* of :math:`t`: - -.. math:: - t \triangleright … \triangleright λ x_1 :T_1 .~…λ x_k :T_k .~(v~u_1 … u_m ) - -where :math:`v` is not an abstraction (nor an application). Note that the head -normal form must not be confused with the normal form since some :math:`u_i` -can be reducible. Similar notions of head-normal forms involving δ, ι -and ζ reductions or any combination of those can also be defined. - - .. _inductive-definitions: Inductive Definitions @@ -1939,166 +1208,3 @@ possible: The principles of mutual induction can be automatically generated using the Scheme command described in Section :ref:`proofschemes-induction-principles`. - - -.. _Admissible-rules-for-global-environments: - -Admissible rules for global environments --------------------------------------------- - -From the original rules of the type system, one can show the -admissibility of rules which change the local context of definition of -objects in the global environment. We show here the admissible rules -that are used in the discharge mechanism at the end of a section. - - -.. _Abstraction: - -**Abstraction.** -One can modify a global declaration by generalizing it over a -previously assumed constant :math:`c`. For doing that, we need to modify the -reference to the global declaration in the subsequent global -environment and local context by explicitly applying this constant to -the constant :math:`c`. - -Below, if :math:`Γ` is a context of the form :math:`[y_1 :A_1 ;~…;~y_n :A_n]`, we write -:math:`∀x:U,~\subst{Γ}{c}{x}` to mean -:math:`[y_1 :∀ x:U,~\subst{A_1}{c}{x};~…;~y_n :∀ x:U,~\subst{A_n}{c}{x}]` -and :math:`\subst{E}{|Γ|}{|Γ|c}` to mean the parallel substitution -:math:`E\{y_1 /(y_1~c)\}…\{y_n/(y_n~c)\}`. - - -.. _First-abstracting-property: - -**First abstracting property:** - -.. math:: - \frac{\WF{E;~c:U;~E′;~c′:=t:T;~E″}{Γ}} - {\WF{E;~c:U;~E′;~c′:=λ x:U.~\subst{t}{c}{x}:∀x:U,~\subst{T}{c}{x};~\subst{E″}{c′}{(c′~c)}} - {\subst{Γ}{c′}{(c′~c)}}} - - -.. math:: - \frac{\WF{E;~c:U;~E′;~c′:T;~E″}{Γ}} - {\WF{E;~c:U;~E′;~c′:∀ x:U,~\subst{T}{c}{x};~\subst{E″}{c′}{(c′~c)}}{\subst{Γ}{c′}{(c′~c)}}} - -.. math:: - \frac{\WF{E;~c:U;~E′;~\ind{p}{Γ_I}{Γ_C};~E″}{Γ}} - {\WFTWOLINES{E;~c:U;~E′;~\ind{p+1}{∀ x:U,~\subst{Γ_I}{c}{x}}{∀ x:U,~\subst{Γ_C}{c}{x}};~ - \subst{E″}{|Γ_I ;Γ_C |}{|Γ_I ;Γ_C | c}} - {\subst{Γ}{|Γ_I ;Γ_C|}{|Γ_I ;Γ_C | c}}} - -One can similarly modify a global declaration by generalizing it over -a previously defined constant :math:`c`. Below, if :math:`Γ` is a context of the form -:math:`[y_1 :A_1 ;~…;~y_n :A_n]`, we write :math:`\subst{Γ}{c}{u}` to mean -:math:`[y_1 :\subst{A_1} {c}{u};~…;~y_n:\subst{A_n} {c}{u}]`. - - -.. _Second-abstracting-property: - -**Second abstracting property:** - -.. math:: - \frac{\WF{E;~c:=u:U;~E′;~c′:=t:T;~E″}{Γ}} - {\WF{E;~c:=u:U;~E′;~c′:=(\letin{x}{u:U}{\subst{t}{c}{x}}):\subst{T}{c}{u};~E″}{Γ}} - -.. math:: - \frac{\WF{E;~c:=u:U;~E′;~c′:T;~E″}{Γ}} - {\WF{E;~c:=u:U;~E′;~c′:\subst{T}{c}{u};~E″}{Γ}} - -.. math:: - \frac{\WF{E;~c:=u:U;~E′;~\ind{p}{Γ_I}{Γ_C};~E″}{Γ}} - {\WF{E;~c:=u:U;~E′;~\ind{p}{\subst{Γ_I}{c}{u}}{\subst{Γ_C}{c}{u}};~E″}{Γ}} - -.. _Pruning-the-local-context: - -**Pruning the local context.** -If one abstracts or substitutes constants with the above rules then it -may happen that some declared or defined constant does not occur any -more in the subsequent global environment and in the local context. -One can consequently derive the following property. - - -.. _First-pruning-property: - -.. inference:: First pruning property: - - \WF{E;~c:U;~E′}{Γ} - c~\kw{does not occur in}~E′~\kw{and}~Γ - -------------------------------------- - \WF{E;E′}{Γ} - - -.. _Second-pruning-property: - -.. inference:: Second pruning property: - - \WF{E;~c:=u:U;~E′}{Γ} - c~\kw{does not occur in}~E′~\kw{and}~Γ - -------------------------------------- - \WF{E;E′}{Γ} - - -.. _Co-inductive-types: - -Co-inductive types ----------------------- - -The implementation contains also co-inductive definitions, which are -types inhabited by infinite objects. More information on co-inductive -definitions can be found in :cite:`Gimenez95b,Gim98,GimCas05`. - - -.. _The-Calculus-of-Inductive-Construction-with-impredicative-Set: - -The Calculus of Inductive Constructions with impredicative Set ------------------------------------------------------------------ - -|Coq| can be used as a type checker for the Calculus of Inductive -Constructions with an impredicative sort :math:`\Set` by using the compiler -option ``-impredicative-set``. For example, using the ordinary `coqtop` -command, the following is rejected, - -.. example:: - - .. coqtop:: all - - Fail Definition id: Set := forall X:Set,X->X. - -while it will type check, if one uses instead the `coqtop` -``-impredicative-set`` option.. - -The major change in the theory concerns the rule for product formation -in the sort :math:`\Set`, which is extended to a domain in any sort: - -.. inference:: ProdImp - - E[Γ] ⊢ T : s - s ∈ \Sort - E[Γ::(x:T)] ⊢ U : \Set - --------------------- - E[Γ] ⊢ ∀ x:T,~U : \Set - -This extension has consequences on the inductive definitions which are -allowed. In the impredicative system, one can build so-called *large -inductive definitions* like the example of second-order existential -quantifier (:g:`exSet`). - -There should be restrictions on the eliminations which can be -performed on such definitions. The elimination rules in the -impredicative system for sort :math:`\Set` become: - - - -.. inference:: Set1 - - s ∈ \{\Prop, \Set\} - ----------------- - [I:\Set|I→ s] - -.. inference:: Set2 - - I~\kw{is a small inductive definition} - s ∈ \{\Type(i)\} - ---------------- - [I:\Set|I→ s] -- cgit v1.2.3 From 75d32b4abaeefb505d62ae201c0edc555f473396 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 20:11:07 +0200 Subject: Create new file on Inductive types. --- doc/sphinx/language/cic.rst | 1210 -------------------------------- doc/sphinx/language/core/inductive.rst | 1210 ++++++++++++++++++++++++++++++++ 2 files changed, 1210 insertions(+), 1210 deletions(-) delete mode 100644 doc/sphinx/language/cic.rst create mode 100644 doc/sphinx/language/core/inductive.rst diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst deleted file mode 100644 index 678374e83e..0000000000 --- a/doc/sphinx/language/cic.rst +++ /dev/null @@ -1,1210 +0,0 @@ -.. _inductive-definitions: - -Inductive Definitions -------------------------- - -Formally, we can represent any *inductive definition* as -:math:`\ind{p}{Γ_I}{Γ_C}` where: - -+ :math:`Γ_I` determines the names and types of inductive types; -+ :math:`Γ_C` determines the names and types of constructors of these - inductive types; -+ :math:`p` determines the number of parameters of these inductive types. - - -These inductive definitions, together with global assumptions and -global definitions, then form the global environment. Additionally, -for any :math:`p` there always exists :math:`Γ_P =[a_1 :A_1 ;~…;~a_p :A_p ]` such that -each :math:`T` in :math:`(t:T)∈Γ_I \cup Γ_C` can be written as: :math:`∀Γ_P , T'` where :math:`Γ_P` is -called the *context of parameters*. Furthermore, we must have that -each :math:`T` in :math:`(t:T)∈Γ_I` can be written as: :math:`∀Γ_P,∀Γ_{\mathit{Arr}(t)}, S` where -:math:`Γ_{\mathit{Arr}(t)}` is called the *Arity* of the inductive type :math:`t` and :math:`S` is called -the sort of the inductive type :math:`t` (not to be confused with :math:`\Sort` which is the set of sorts). - -.. example:: - - The declaration for parameterized lists is: - - .. math:: - \ind{1}{[\List:\Set→\Set]}{\left[\begin{array}{rcl} - \Nil & : & ∀ A:\Set,~\List~A \\ - \cons & : & ∀ A:\Set,~A→ \List~A→ \List~A - \end{array} - \right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive list (A:Set) : Set := - | nil : list A - | cons : A -> list A -> list A. - -.. example:: - - The declaration for a mutual inductive definition of tree and forest - is: - - .. math:: - \ind{0}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]} - {\left[\begin{array}{rcl} - \node &:& \forest → \tree\\ - \emptyf &:& \forest\\ - \consf &:& \tree → \forest → \forest\\ - \end{array}\right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive tree : Set := - | node : forest -> tree - with forest : Set := - | emptyf : forest - | consf : tree -> forest -> forest. - -.. example:: - - The declaration for a mutual inductive definition of even and odd is: - - .. math:: - \ind{0}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\ - \odd&:&\nat → \Prop \end{array}\right]} - {\left[\begin{array}{rcl} - \evenO &:& \even~0\\ - \evenS &:& ∀ n,~\odd~n → \even~(\nS~n)\\ - \oddS &:& ∀ n,~\even~n → \odd~(\nS~n) - \end{array}\right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive even : nat -> Prop := - | even_O : even 0 - | even_S : forall n, odd n -> even (S n) - with odd : nat -> Prop := - | odd_S : forall n, even n -> odd (S n). - - - -.. _Types-of-inductive-objects: - -Types of inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We have to give the type of constants in a global environment :math:`E` which -contains an inductive definition. - -.. inference:: Ind - - \WFE{Γ} - \ind{p}{Γ_I}{Γ_C} ∈ E - (a:A)∈Γ_I - --------------------- - E[Γ] ⊢ a : A - -.. inference:: Constr - - \WFE{Γ} - \ind{p}{Γ_I}{Γ_C} ∈ E - (c:C)∈Γ_C - --------------------- - E[Γ] ⊢ c : C - -.. example:: - - Provided that our environment :math:`E` contains inductive definitions we showed before, - these two inference rules above enable us to conclude that: - - .. math:: - \begin{array}{l} - E[Γ] ⊢ \even : \nat→\Prop\\ - E[Γ] ⊢ \odd : \nat→\Prop\\ - E[Γ] ⊢ \evenO : \even~\nO\\ - E[Γ] ⊢ \evenS : ∀ n:\nat,~\odd~n → \even~(\nS~n)\\ - E[Γ] ⊢ \oddS : ∀ n:\nat,~\even~n → \odd~(\nS~n) - \end{array} - - - - -.. _Well-formed-inductive-definitions: - -Well-formed inductive definitions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We cannot accept any inductive definition because some of them lead -to inconsistent systems. We restrict ourselves to definitions which -satisfy a syntactic criterion of positivity. Before giving the formal -rules, we need a few definitions: - -Arity of a given sort -+++++++++++++++++++++ - -A type :math:`T` is an *arity of sort* :math:`s` if it converts to the sort :math:`s` or to a -product :math:`∀ x:T,~U` with :math:`U` an arity of sort :math:`s`. - -.. example:: - - :math:`A→\Set` is an arity of sort :math:`\Set`. :math:`∀ A:\Prop,~A→ \Prop` is an arity of sort - :math:`\Prop`. - - -Arity -+++++ -A type :math:`T` is an *arity* if there is a :math:`s∈ \Sort` such that :math:`T` is an arity of -sort :math:`s`. - - -.. example:: - - :math:`A→ \Set` and :math:`∀ A:\Prop,~A→ \Prop` are arities. - - -Type of constructor -+++++++++++++++++++ -We say that :math:`T` is a *type of constructor of* :math:`I` in one of the following -two cases: - -+ :math:`T` is :math:`(I~t_1 … t_n )` -+ :math:`T` is :math:`∀ x:U,~T'` where :math:`T'` is also a type of constructor of :math:`I` - -.. example:: - - :math:`\nat` and :math:`\nat→\nat` are types of constructor of :math:`\nat`. - :math:`∀ A:\Type,~\List~A` and :math:`∀ A:\Type,~A→\List~A→\List~A` are types of constructor of :math:`\List`. - -.. _positivity: - -Positivity Condition -++++++++++++++++++++ - -The type of constructor :math:`T` will be said to *satisfy the positivity -condition* for a constant :math:`X` in the following cases: - -+ :math:`T=(X~t_1 … t_n )` and :math:`X` does not occur free in any :math:`t_i` -+ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` - satisfies the positivity condition for :math:`X`. - -Strict positivity -+++++++++++++++++ - -The constant :math:`X` *occurs strictly positively* in :math:`T` in the following -cases: - - -+ :math:`X` does not occur in :math:`T` -+ :math:`T` converts to :math:`(X~t_1 … t_n )` and :math:`X` does not occur in any of :math:`t_i` -+ :math:`T` converts to :math:`∀ x:U,~V` and :math:`X` does not occur in type :math:`U` but occurs - strictly positively in type :math:`V` -+ :math:`T` converts to :math:`(I~a_1 … a_m~t_1 … t_p )` where :math:`I` is the name of an - inductive definition of the form - - .. math:: - \ind{m}{I:A}{c_1 :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_1 ;~…;~c_n :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_n} - - (in particular, it is - not mutually defined and it has :math:`m` parameters) and :math:`X` does not occur in - any of the :math:`t_i`, and the (instantiated) types of constructor - :math:`\subst{C_i}{p_j}{a_j}_{j=1… m}` of :math:`I` satisfy the nested positivity condition for :math:`X` - -Nested Positivity -+++++++++++++++++ - -The type of constructor :math:`T` of :math:`I` *satisfies the nested positivity -condition* for a constant :math:`X` in the following cases: - -+ :math:`T=(I~b_1 … b_m~u_1 … u_p)`, :math:`I` is an inductive type with :math:`m` - parameters and :math:`X` does not occur in any :math:`u_i` -+ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` - satisfies the nested positivity condition for :math:`X` - - -.. example:: - - For instance, if one considers the following variant of a tree type - branching over the natural numbers: - - .. coqtop:: in - - Inductive nattree (A:Type) : Type := - | leaf : nattree A - | natnode : A -> (nat -> nattree A) -> nattree A. - - Then every instantiated constructor of ``nattree A`` satisfies the nested positivity - condition for ``nattree``: - - + Type ``nattree A`` of constructor ``leaf`` satisfies the positivity condition for - ``nattree`` because ``nattree`` does not appear in any (real) arguments of the - type of that constructor (primarily because ``nattree`` does not have any (real) - arguments) ... (bullet 1) - - + Type ``A → (nat → nattree A) → nattree A`` of constructor ``natnode`` satisfies the - positivity condition for ``nattree`` because: - - - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 1) - - - ``nattree`` occurs only strictly positively in ``nat → nattree A`` ... (bullet 3 + 2) - - - ``nattree`` satisfies the positivity condition for ``nattree A`` ... (bullet 1) - -.. _Correctness-rules: - -Correctness rules -+++++++++++++++++ - -We shall now describe the rules allowing the introduction of a new -inductive definition. - -Let :math:`E` be a global environment and :math:`Γ_P`, :math:`Γ_I`, :math:`Γ_C` be contexts -such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k]`, and -:math:`Γ_C` is :math:`[c_1:∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n ]`. Then - -.. inference:: W-Ind - - \WFE{Γ_P} - (E[Γ_I ;Γ_P ] ⊢ C_i : s_{q_i} )_{i=1… n} - ------------------------------------------ - \WF{E;~\ind{p}{Γ_I}{Γ_C}}{} - - -provided that the following side conditions hold: - - + :math:`k>0` and all of :math:`I_j` and :math:`c_i` are distinct names for :math:`j=1… k` and :math:`i=1… n`, - + :math:`p` is the number of parameters of :math:`\ind{p}{Γ_I}{Γ_C}` and :math:`Γ_P` is the - context of parameters, - + for :math:`j=1… k` we have that :math:`A_j` is an arity of sort :math:`s_j` and :math:`I_j ∉ E`, - + for :math:`i=1… n` we have that :math:`C_i` is a type of constructor of :math:`I_{q_i}` which - satisfies the positivity condition for :math:`I_1 … I_k` and :math:`c_i ∉ E`. - -One can remark that there is a constraint between the sort of the -arity of the inductive type and the sort of the type of its -constructors which will always be satisfied for the impredicative -sorts :math:`\SProp` and :math:`\Prop` but may fail to define -inductive type on sort :math:`\Set` and generate constraints -between universes for inductive types in the Type hierarchy. - - -.. example:: - - It is well known that the existential quantifier can be encoded as an - inductive definition. The following declaration introduces the - second-order existential quantifier :math:`∃ X.P(X)`. - - .. coqtop:: in - - Inductive exProp (P:Prop->Prop) : Prop := - | exP_intro : forall X:Prop, P X -> exProp P. - - The same definition on :math:`\Set` is not allowed and fails: - - .. coqtop:: all - - Fail Inductive exSet (P:Set->Prop) : Set := - exS_intro : forall X:Set, P X -> exSet P. - - It is possible to declare the same inductive definition in the - universe :math:`\Type`. The :g:`exType` inductive definition has type - :math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT}_{\kw{intro}}` - has type :math:`\Type(k)` with :math:`kProp) : Type := - exT_intro : forall X:Type, P X -> exType P. - - -.. example:: Negative occurrence (first example) - - The following inductive definition is rejected because it does not - satisfy the positivity condition: - - .. coqtop:: all - - Fail Inductive I : Prop := not_I_I (not_I : I -> False) : I. - - If we were to accept such definition, we could derive a - contradiction from it (we can test this by disabling the - :flag:`Positivity Checking` flag): - - .. coqtop:: none - - Unset Positivity Checking. - Inductive I : Prop := not_I_I (not_I : I -> False) : I. - Set Positivity Checking. - - .. coqtop:: all - - Definition I_not_I : I -> ~ I := fun i => - match i with not_I_I not_I => not_I end. - - .. coqtop:: in - - Lemma contradiction : False. - Proof. - enough (I /\ ~ I) as [] by contradiction. - split. - - apply not_I_I. - intro. - now apply I_not_I. - - intro. - now apply I_not_I. - Qed. - -.. example:: Negative occurrence (second example) - - Here is another example of an inductive definition which is - rejected because it does not satify the positivity condition: - - .. coqtop:: all - - Fail Inductive Lam := lam (_ : Lam -> Lam). - - Again, if we were to accept it, we could derive a contradiction - (this time through a non-terminating recursive function): - - .. coqtop:: none - - Unset Positivity Checking. - Inductive Lam := lam (_ : Lam -> Lam). - Set Positivity Checking. - - .. coqtop:: all - - Fixpoint infinite_loop l : False := - match l with lam x => infinite_loop (x l) end. - - Check infinite_loop (lam (@id Lam)) : False. - -.. example:: Non strictly positive occurrence - - It is less obvious why inductive type definitions with occurences - that are positive but not strictly positive are harmful. - We will see that in presence of an impredicative type they - are unsound: - - .. coqtop:: all - - Fail Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. - - If we were to accept this definition we could derive a contradiction - by creating an injective function from :math:`A → \Prop` to :math:`A`. - - This function is defined by composing the injective constructor of - the type :math:`A` with the function :math:`λx. λz. z = x` injecting - any type :math:`T` into :math:`T → \Prop`. - - .. coqtop:: none - - Unset Positivity Checking. - Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. - Set Positivity Checking. - - .. coqtop:: all - - Definition f (x: A -> Prop): A := introA (fun z => z = x). - - .. coqtop:: in - - Lemma f_inj: forall x y, f x = f y -> x = y. - Proof. - unfold f; intros ? ? H; injection H. - set (F := fun z => z = y); intro HF. - symmetry; replace (y = x) with (F y). - + unfold F; reflexivity. - + rewrite <- HF; reflexivity. - Qed. - - The type :math:`A → \Prop` can be understood as the powerset - of the type :math:`A`. To derive a contradiction from the - injective function :math:`f` we use Cantor's classic diagonal - argument. - - .. coqtop:: all - - Definition d: A -> Prop := fun x => exists s, x = f s /\ ~s x. - Definition fd: A := f d. - - .. coqtop:: in - - Lemma cantor: (d fd) <-> ~(d fd). - Proof. - split. - + intros [s [H1 H2]]; unfold fd in H1. - replace d with s. - * assumption. - * apply f_inj; congruence. - + intro; exists d; tauto. - Qed. - - Lemma bad: False. - Proof. - pose cantor; tauto. - Qed. - - This derivation was first presented by Thierry Coquand and Christine - Paulin in :cite:`CP90`. - -.. _Template-polymorphism: - -Template polymorphism -+++++++++++++++++++++ - -Inductive types can be made polymorphic over the universes introduced by -their parameters in :math:`\Type`, if the minimal inferred sort of the -inductive declarations either mention some of those parameter universes -or is computed to be :math:`\Prop` or :math:`\Set`. - -If :math:`A` is an arity of some sort and :math:`s` is a sort, we write :math:`A_{/s}` -for the arity obtained from :math:`A` by replacing its sort with :math:`s`. -Especially, if :math:`A` is well-typed in some global environment and local -context, then :math:`A_{/s}` is typable by typability of all products in the -Calculus of Inductive Constructions. The following typing rule is -added to the theory. - -Let :math:`\ind{p}{Γ_I}{Γ_C}` be an inductive definition. Let -:math:`Γ_P = [p_1 :P_1 ;~…;~p_p :P_p ]` be its context of parameters, -:math:`Γ_I = [I_1:∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k ]` its context of definitions and -:math:`Γ_C = [c_1 :∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n]` its context of constructors, -with :math:`c_i` a constructor of :math:`I_{q_i}`. Let :math:`m ≤ p` be the length of the -longest prefix of parameters such that the :math:`m` first arguments of all -occurrences of all :math:`I_j` in all :math:`C_k` (even the occurrences in the -hypotheses of :math:`C_k`) are exactly applied to :math:`p_1 … p_m` (:math:`m` is the number -of *recursively uniform parameters* and the :math:`p−m` remaining parameters -are the *recursively non-uniform parameters*). Let :math:`q_1 , …, q_r`, with -:math:`0≤ r≤ m`, be a (possibly) partial instantiation of the recursively -uniform parameters of :math:`Γ_P`. We have: - -.. inference:: Ind-Family - - \left\{\begin{array}{l} - \ind{p}{Γ_I}{Γ_C} \in E\\ - (E[] ⊢ q_l : P'_l)_{l=1\ldots r}\\ - (E[] ⊢ P'_l ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1})_{l=1\ldots r}\\ - 1 \leq j \leq k - \end{array} - \right. - ----------------------------- - E[] ⊢ I_j~q_1 … q_r :∀ [p_{r+1} :P_{r+1} ;~…;~p_p :P_p], (A_j)_{/s_j} - -provided that the following side conditions hold: - - + :math:`Γ_{P′}` is the context obtained from :math:`Γ_P` by replacing each :math:`P_l` that is - an arity with :math:`P_l'` for :math:`1≤ l ≤ r` (notice that :math:`P_l` arity implies :math:`P_l'` - arity since :math:`E[] ⊢ P_l' ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1}`); - + there are sorts :math:`s_i`, for :math:`1 ≤ i ≤ k` such that, for - :math:`Γ_{I'} = [I_1 :∀ Γ_{P'} ,(A_1)_{/s_1} ;~…;~I_k :∀ Γ_{P'} ,(A_k)_{/s_k}]` - we have :math:`(E[Γ_{I′} ;Γ_{P′}] ⊢ C_i : s_{q_i})_{i=1… n}` ; - + the sorts :math:`s_i` are all introduced by the inductive - declaration and have no universe constraints beside being greater - than or equal to :math:`\Prop`, and such that all - eliminations, to :math:`\Prop`, :math:`\Set` and :math:`\Type(j)`, - are allowed (see Section :ref:`Destructors`). - - -Notice that if :math:`I_j~q_1 … q_r` is typable using the rules **Ind-Const** and -**App**, then it is typable using the rule **Ind-Family**. Conversely, the -extended theory is not stronger than the theory without **Ind-Family**. We -get an equiconsistency result by mapping each :math:`\ind{p}{Γ_I}{Γ_C}` -occurring into a given derivation into as many different inductive -types and constructors as the number of different (partial) -replacements of sorts, needed for this derivation, in the parameters -that are arities (this is possible because :math:`\ind{p}{Γ_I}{Γ_C}` well-formed -implies that :math:`\ind{p}{Γ_{I'}}{Γ_{C'}}` is well-formed and has the -same allowed eliminations, where :math:`Γ_{I′}` is defined as above and -:math:`Γ_{C′} = [c_1 :∀ Γ_{P′} ,C_1 ;~…;~c_n :∀ Γ_{P′} ,C_n ]`). That is, the changes in the -types of each partial instance :math:`q_1 … q_r` can be characterized by the -ordered sets of arity sorts among the types of parameters, and to each -signature is associated a new inductive definition with fresh names. -Conversion is preserved as any (partial) instance :math:`I_j~q_1 … q_r` or -:math:`C_i~q_1 … q_r` is mapped to the names chosen in the specific instance of -:math:`\ind{p}{Γ_I}{Γ_C}`. - -.. warning:: - - The restriction that sorts are introduced by the inductive - declaration prevents inductive types declared in sections to be - template-polymorphic on universes introduced previously in the - section: they cannot parameterize over the universes introduced with - section variables that become parameters at section closing time, as - these may be shared with other definitions from the same section - which can impose constraints on them. - -.. flag:: Auto Template Polymorphism - - This flag, enabled by default, makes every inductive type declared - at level :math:`\Type` (without annotations or hiding it behind a - definition) template polymorphic if possible. - - This can be prevented using the :attr:`universes(notemplate)` - attribute. - - Template polymorphism and full universe polymorphism (see Chapter - :ref:`polymorphicuniverses`) are incompatible, so if the latter is - enabled (through the :flag:`Universe Polymorphism` flag or the - :attr:`universes(polymorphic)` attribute) it will prevail over - automatic template polymorphism. - -.. warn:: Automatically declaring @ident as template polymorphic. - - Warning ``auto-template`` can be used (it is off by default) to - find which types are implicitly declared template polymorphic by - :flag:`Auto Template Polymorphism`. - - An inductive type can be forced to be template polymorphic using - the :attr:`universes(template)` attribute: in this case, the - warning is not emitted. - -.. attr:: universes(template) - - This attribute can be used to explicitly declare an inductive type - as template polymorphic, whether the :flag:`Auto Template - Polymorphism` flag is on or off. - - .. exn:: template and polymorphism not compatible - - This attribute cannot be used in a full universe polymorphic - context, i.e. if the :flag:`Universe Polymorphism` flag is on or - if the :attr:`universes(polymorphic)` attribute is used. - - .. exn:: Ill-formed template inductive declaration: not polymorphic on any universe. - - The attribute was used but the inductive definition does not - satisfy the criterion to be template polymorphic. - -.. attr:: universes(notemplate) - - This attribute can be used to prevent an inductive type to be - template polymorphic, even if the :flag:`Auto Template - Polymorphism` flag is on. - -In practice, the rule **Ind-Family** is used by |Coq| only when all the -inductive types of the inductive definition are declared with an arity -whose sort is in the Type hierarchy. Then, the polymorphism is over -the parameters whose type is an arity of sort in the Type hierarchy. -The sorts :math:`s_j` are chosen canonically so that each :math:`s_j` is minimal with -respect to the hierarchy :math:`\Prop ⊂ \Set_p ⊂ \Type` where :math:`\Set_p` is predicative -:math:`\Set`. More precisely, an empty or small singleton inductive definition -(i.e. an inductive definition of which all inductive types are -singleton – see Section :ref:`Destructors`) is set in :math:`\Prop`, a small non-singleton -inductive type is set in :math:`\Set` (even in case :math:`\Set` is impredicative – see -Section The-Calculus-of-Inductive-Construction-with-impredicative-Set_), -and otherwise in the Type hierarchy. - -Note that the side-condition about allowed elimination sorts in the rule -**Ind-Family** avoids to recompute the allowed elimination sorts at each -instance of a pattern matching (see Section :ref:`Destructors`). As an -example, let us consider the following definition: - -.. example:: - - .. coqtop:: in - - Inductive option (A:Type) : Type := - | None : option A - | Some : A -> option A. - -As the definition is set in the Type hierarchy, it is used -polymorphically over its parameters whose types are arities of a sort -in the Type hierarchy. Here, the parameter :math:`A` has this property, hence, -if :g:`option` is applied to a type in :math:`\Set`, the result is in :math:`\Set`. Note that -if :g:`option` is applied to a type in :math:`\Prop`, then, the result is not set in -:math:`\Prop` but in :math:`\Set` still. This is because :g:`option` is not a singleton type -(see Section :ref:`Destructors`) and it would lose the elimination to :math:`\Set` and :math:`\Type` -if set in :math:`\Prop`. - -.. example:: - - .. coqtop:: all - - Check (fun A:Set => option A). - Check (fun A:Prop => option A). - -Here is another example. - -.. example:: - - .. coqtop:: in - - Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. - -As :g:`prod` is a singleton type, it will be in :math:`\Prop` if applied twice to -propositions, in :math:`\Set` if applied twice to at least one type in :math:`\Set` and -none in :math:`\Type`, and in :math:`\Type` otherwise. In all cases, the three kind of -eliminations schemes are allowed. - -.. example:: - - .. coqtop:: all - - Check (fun A:Set => prod A). - Check (fun A:Prop => prod A A). - Check (fun (A:Prop) (B:Set) => prod A B). - Check (fun (A:Type) (B:Prop) => prod A B). - -.. note:: - Template polymorphism used to be called “sort-polymorphism of - inductive types” before universe polymorphism - (see Chapter :ref:`polymorphicuniverses`) was introduced. - - -.. _Destructors: - -Destructors -~~~~~~~~~~~~~~~~~ - -The specification of inductive definitions with arities and -constructors is quite natural. But we still have to say how to use an -object in an inductive type. - -This problem is rather delicate. There are actually several different -ways to do that. Some of them are logically equivalent but not always -equivalent from the computational point of view or from the user point -of view. - -From the computational point of view, we want to be able to define a -function whose domain is an inductively defined type by using a -combination of case analysis over the possible constructors of the -object and recursion. - -Because we need to keep a consistent theory and also we prefer to keep -a strongly normalizing reduction, we cannot accept any sort of -recursion (even terminating). So the basic idea is to restrict -ourselves to primitive recursive functions and functionals. - -For instance, assuming a parameter :math:`A:\Set` exists in the local context, -we want to build a function :math:`\length` of type :math:`\List~A → \nat` which computes -the length of the list, such that :math:`(\length~(\Nil~A)) = \nO` and -:math:`(\length~(\cons~A~a~l)) = (\nS~(\length~l))`. -We want these equalities to be -recognized implicitly and taken into account in the conversion rule. - -From the logical point of view, we have built a type family by giving -a set of constructors. We want to capture the fact that we do not have -any other way to build an object in this type. So when trying to prove -a property about an object :math:`m` in an inductive type it is enough -to enumerate all the cases where :math:`m` starts with a different -constructor. - -In case the inductive definition is effectively a recursive one, we -want to capture the extra property that we have built the smallest -fixed point of this recursive equation. This says that we are only -manipulating finite objects. This analysis provides induction -principles. For instance, in order to prove -:math:`∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l))` it is enough to prove: - - -+ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~(\length~(\Nil~A)))` -+ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` - :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\length~(\cons~A~a~l)))` - - -which given the conversion equalities satisfied by :math:`\length` is the same -as proving: - - -+ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~\nO)` -+ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` - :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\nS~(\length~l)))` - - -One conceptually simple way to do that, following the basic scheme -proposed by Martin-Löf in his Intuitionistic Type Theory, is to -introduce for each inductive definition an elimination operator. At -the logical level it is a proof of the usual induction principle and -at the computational level it implements a generic operator for doing -primitive recursion over the structure. - -But this operator is rather tedious to implement and use. We choose in -this version of |Coq| to factorize the operator for primitive recursion -into two more primitive operations as was first suggested by Th. -Coquand in :cite:`Coq92`. One is the definition by pattern matching. The -second one is a definition by guarded fixpoints. - - -.. _match-construction: - -The match ... with ... end construction -+++++++++++++++++++++++++++++++++++++++ - -The basic idea of this operator is that we have an object :math:`m` in an -inductive type :math:`I` and we want to prove a property which possibly -depends on :math:`m`. For this, it is enough to prove the property for -:math:`m = (c_i~u_1 … u_{p_i} )` for each constructor of :math:`I`. -The |Coq| term for this proof -will be written: - -.. math:: - \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend - -In this expression, if :math:`m` eventually happens to evaluate to -:math:`(c_i~u_1 … u_{p_i})` then the expression will behave as specified in its :math:`i`-th branch -and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are replaced by the -:math:`u_1 … u_{p_i}` according to the ι-reduction. - -Actually, for type checking a :math:`\Match…\with…\kwend` expression we also need -to know the predicate :math:`P` to be proved by case analysis. In the general -case where :math:`I` is an inductively defined :math:`n`-ary relation, :math:`P` is a predicate -over :math:`n+1` arguments: the :math:`n` first ones correspond to the arguments of :math:`I` -(parameters excluded), and the last one corresponds to object :math:`m`. |Coq| -can sometimes infer this predicate but sometimes not. The concrete -syntax for describing this predicate uses the :math:`\as…\In…\return` -construction. For instance, let us assume that :math:`I` is an unary predicate -with one parameter and one argument. The predicate is made explicit -using the syntax: - -.. math:: - \Match~m~\as~x~\In~I~\_~a~\return~P~\with~ - (c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … - | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend - -The :math:`\as` part can be omitted if either the result type does not depend -on :math:`m` (non-dependent elimination) or :math:`m` is a variable (in this case, :math:`m` -can occur in :math:`P` where it is considered a bound variable). The :math:`\In` part -can be omitted if the result type does not depend on the arguments -of :math:`I`. Note that the arguments of :math:`I` corresponding to parameters *must* -be :math:`\_`, because the result type is not generalized to all possible -values of the parameters. The other arguments of :math:`I` (sometimes called -indices in the literature) have to be variables (:math:`a` above) and these -variables can occur in :math:`P`. The expression after :math:`\In` must be seen as an -*inductive type pattern*. Notice that expansion of implicit arguments -and notations apply to this pattern. For the purpose of presenting the -inference rules, we use a more compact notation: - -.. math:: - \case(m,(λ a x . P), λ x_{11} ... x_{1p_1} . f_1~| … |~λ x_{n1} ...x_{np_n} . f_n ) - - -.. _Allowed-elimination-sorts: - -**Allowed elimination sorts.** An important question for building the typing rule for :math:`\Match` is what -can be the type of :math:`λ a x . P` with respect to the type of :math:`m`. If :math:`m:I` -and :math:`I:A` and :math:`λ a x . P : B` then by :math:`[I:A|B]` we mean that one can use -:math:`λ a x . P` with :math:`m` in the above match-construct. - - -.. _cic_notations: - -**Notations.** The :math:`[I:A|B]` is defined as the smallest relation satisfying the -following rules: We write :math:`[I|B]` for :math:`[I:A|B]` where :math:`A` is the type of :math:`I`. - -The case of inductive types in sorts :math:`\Set` or :math:`\Type` is simple. -There is no restriction on the sort of the predicate to be eliminated. - -.. inference:: Prod - - [(I~x):A′|B′] - ----------------------- - [I:∀ x:A,~A′|∀ x:A,~B′] - - -.. inference:: Set & Type - - s_1 ∈ \{\Set,\Type(j)\} - s_2 ∈ \Sort - ---------------- - [I:s_1 |I→ s_2 ] - - -The case of Inductive definitions of sort :math:`\Prop` is a bit more -complicated, because of our interpretation of this sort. The only -harmless allowed eliminations, are the ones when predicate :math:`P` -is also of sort :math:`\Prop` or is of the morally smaller sort -:math:`\SProp`. - -.. inference:: Prop - - s ∈ \{\SProp,\Prop\} - -------------------- - [I:\Prop|I→s] - - -:math:`\Prop` is the type of logical propositions, the proofs of properties :math:`P` in -:math:`\Prop` could not be used for computation and are consequently ignored by -the extraction mechanism. Assume :math:`A` and :math:`B` are two propositions, and the -logical disjunction :math:`A ∨ B` is defined inductively by: - -.. example:: - - .. coqtop:: in - - Inductive or (A B:Prop) : Prop := - or_introl : A -> or A B | or_intror : B -> or A B. - - -The following definition which computes a boolean value by case over -the proof of :g:`or A B` is not accepted: - -.. example:: - - .. coqtop:: all - - Fail Definition choice (A B: Prop) (x:or A B) := - match x with or_introl _ _ a => true | or_intror _ _ b => false end. - -From the computational point of view, the structure of the proof of -:g:`(or A B)` in this term is needed for computing the boolean value. - -In general, if :math:`I` has type :math:`\Prop` then :math:`P` cannot have type :math:`I→\Set`, because -it will mean to build an informative proof of type :math:`(P~m)` doing a case -analysis over a non-computational object that will disappear in the -extracted program. But the other way is safe with respect to our -interpretation we can have :math:`I` a computational object and :math:`P` a -non-computational one, it just corresponds to proving a logical property -of a computational object. - -In the same spirit, elimination on :math:`P` of type :math:`I→\Type` cannot be allowed -because it trivially implies the elimination on :math:`P` of type :math:`I→ \Set` by -cumulativity. It also implies that there are two proofs of the same -property which are provably different, contradicting the -proof-irrelevance property which is sometimes a useful axiom: - -.. example:: - - .. coqtop:: all - - Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y. - -The elimination of an inductive type of sort :math:`\Prop` on a predicate -:math:`P` of type :math:`I→ \Type` leads to a paradox when applied to impredicative -inductive definition like the second-order existential quantifier -:g:`exProp` defined above, because it gives access to the two projections on -this type. - - -.. _Empty-and-singleton-elimination: - -**Empty and singleton elimination.** There are special inductive definitions in -:math:`\Prop` for which more eliminations are allowed. - -.. inference:: Prop-extended - - I~\kw{is an empty or singleton definition} - s ∈ \Sort - ------------------------------------- - [I:\Prop|I→ s] - -A *singleton definition* has only one constructor and all the -arguments of this constructor have type :math:`\Prop`. In that case, there is a -canonical way to interpret the informative extraction on an object in -that type, such that the elimination on any sort :math:`s` is legal. Typical -examples are the conjunction of non-informative propositions and the -equality. If there is a hypothesis :math:`h:a=b` in the local context, it can -be used for rewriting not only in logical propositions but also in any -type. - -.. example:: - - .. coqtop:: all - - Print eq_rec. - Require Extraction. - Extraction eq_rec. - -An empty definition has no constructors, in that case also, -elimination on any sort is allowed. - -.. _Eliminaton-for-SProp: - -Inductive types in :math:`\SProp` must have no constructors (i.e. be -empty) to be eliminated to produce relevant values. - -Note that thanks to proof irrelevance elimination functions can be -produced for other types, for instance the elimination for a unit type -is the identity. - -.. _Type-of-branches: - -**Type of branches.** -Let :math:`c` be a term of type :math:`C`, we assume :math:`C` is a type of constructor for an -inductive type :math:`I`. Let :math:`P` be a term that represents the property to be -proved. We assume :math:`r` is the number of parameters and :math:`s` is the number of -arguments. - -We define a new type :math:`\{c:C\}^P` which represents the type of the branch -corresponding to the :math:`c:C` constructor. - -.. math:: - \begin{array}{ll} - \{c:(I~q_1\ldots q_r\ t_1 \ldots t_s)\}^P &\equiv (P~t_1\ldots ~t_s~c) \\ - \{c:∀ x:T,~C\}^P &\equiv ∀ x:T,~\{(c~x):C\}^P - \end{array} - -We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:`c`. - - -.. example:: - - The following term in concrete syntax:: - - match t as l return P' with - | nil _ => t1 - | cons _ hd tl => t2 - end - - - can be represented in abstract syntax as - - .. math:: - \case(t,P,f_1 | f_2 ) - - where - - .. math:: - :nowrap: - - \begin{eqnarray*} - P & = & λ l.~P^\prime\\ - f_1 & = & t_1\\ - f_2 & = & λ (hd:\nat).~λ (tl:\List~\nat).~t_2 - \end{eqnarray*} - - According to the definition: - - .. math:: - \{(\Nil~\nat)\}^P ≡ \{(\Nil~\nat) : (\List~\nat)\}^P ≡ (P~(\Nil~\nat)) - - .. math:: - - \begin{array}{rl} - \{(\cons~\nat)\}^P & ≡\{(\cons~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\ - & ≡∀ n:\nat,~\{(\cons~\nat~n) : (\List~\nat→\List~\nat)\}^P \\ - & ≡∀ n:\nat,~∀ l:\List~\nat,~\{(\cons~\nat~n~l) : (\List~\nat)\}^P \\ - & ≡∀ n:\nat,~∀ l:\List~\nat,~(P~(\cons~\nat~n~l)). - \end{array} - - Given some :math:`P` then :math:`\{(\Nil~\nat)\}^P` represents the expected type of :math:`f_1`, - and :math:`\{(\cons~\nat)\}^P` represents the expected type of :math:`f_2`. - - -.. _Typing-rule: - -**Typing rule.** -Our very general destructor for inductive definition enjoys the -following typing rule - -.. inference:: match - - \begin{array}{l} - E[Γ] ⊢ c : (I~q_1 … q_r~t_1 … t_s ) \\ - E[Γ] ⊢ P : B \\ - [(I~q_1 … q_r)|B] \\ - (E[Γ] ⊢ f_i : \{(c_{p_i}~q_1 … q_r)\}^P)_{i=1… l} - \end{array} - ------------------------------------------------ - E[Γ] ⊢ \case(c,P,f_1 |… |f_l ) : (P~t_1 … t_s~c) - -provided :math:`I` is an inductive type in a -definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;~…;~c_n :C_n ]` and -:math:`c_{p_1} … c_{p_l}` are the only constructors of :math:`I`. - - - -.. example:: - - Below is a typing rule for the term shown in the previous example: - - .. inference:: list example - - \begin{array}{l} - E[Γ] ⊢ t : (\List ~\nat) \\ - E[Γ] ⊢ P : B \\ - [(\List ~\nat)|B] \\ - E[Γ] ⊢ f_1 : \{(\Nil ~\nat)\}^P \\ - E[Γ] ⊢ f_2 : \{(\cons ~\nat)\}^P - \end{array} - ------------------------------------------------ - E[Γ] ⊢ \case(t,P,f_1 |f_2 ) : (P~t) - - -.. _Definition-of-ι-reduction: - -**Definition of ι-reduction.** -We still have to define the ι-reduction in the general case. - -An ι-redex is a term of the following form: - -.. math:: - \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) - -with :math:`c_{p_i}` the :math:`i`-th constructor of the inductive type :math:`I` with :math:`r` -parameters. - -The ι-contraction of this term is :math:`(f_i~a_1 … a_m )` leading to the -general reduction rule: - -.. math:: - \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) \triangleright_ι (f_i~a_1 … a_m ) - - -.. _Fixpoint-definitions: - -Fixpoint definitions -~~~~~~~~~~~~~~~~~~~~ - -The second operator for elimination is fixpoint definition. This -fixpoint may involve several mutually recursive definitions. The basic -concrete syntax for a recursive set of mutually recursive declarations -is (with :math:`Γ_i` contexts): - -.. math:: - \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n - - -The terms are obtained by projections from this set of declarations -and are written - -.. math:: - \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n~\for~f_i - -In the inference rules, we represent such a term by - -.. math:: - \Fix~f_i\{f_1 :A_1':=t_1' … f_n :A_n':=t_n'\} - -with :math:`t_i'` (resp. :math:`A_i'`) representing the term :math:`t_i` abstracted (resp. -generalized) with respect to the bindings in the context :math:`Γ_i`, namely -:math:`t_i'=λ Γ_i . t_i` and :math:`A_i'=∀ Γ_i , A_i`. - - -Typing rule -+++++++++++ - -The typing rule is the expected one for a fixpoint. - -.. inference:: Fix - - (E[Γ] ⊢ A_i : s_i )_{i=1… n} - (E[Γ;~f_1 :A_1 ;~…;~f_n :A_n ] ⊢ t_i : A_i )_{i=1… n} - ------------------------------------------------------- - E[Γ] ⊢ \Fix~f_i\{f_1 :A_1 :=t_1 … f_n :A_n :=t_n \} : A_i - - -Any fixpoint definition cannot be accepted because non-normalizing -terms allow proofs of absurdity. The basic scheme of recursion that -should be allowed is the one needed for defining primitive recursive -functionals. In that case the fixpoint enjoys a special syntactic -restriction, namely one of the arguments belongs to an inductive type, -the function starts with a case analysis and recursive calls are done -on variables coming from patterns and representing subterms. For -instance in the case of natural numbers, a proof of the induction -principle of type - -.. math:: - ∀ P:\nat→\Prop,~(P~\nO)→(∀ n:\nat,~(P~n)→(P~(\nS~n)))→ ∀ n:\nat,~(P~n) - -can be represented by the term: - -.. math:: - \begin{array}{l} - λ P:\nat→\Prop.~λ f:(P~\nO).~λ g:(∀ n:\nat,~(P~n)→(P~(\nS~n))).\\ - \Fix~h\{h:∀ n:\nat,~(P~n):=λ n:\nat.~\case(n,P,f | λp:\nat.~(g~p~(h~p)))\} - \end{array} - -Before accepting a fixpoint definition as being correctly typed, we -check that the definition is “guarded”. A precise analysis of this -notion can be found in :cite:`Gim94`. The first stage is to precise on which -argument the fixpoint will be decreasing. The type of this argument -should be an inductive type. For doing this, the syntax of -fixpoints is extended and becomes - -.. math:: - \Fix~f_i\{f_1/k_1 :A_1:=t_1 … f_n/k_n :A_n:=t_n\} - - -where :math:`k_i` are positive integers. Each :math:`k_i` represents the index of -parameter of :math:`f_i`, on which :math:`f_i` is decreasing. Each :math:`A_i` should be a -type (reducible to a term) starting with at least :math:`k_i` products -:math:`∀ y_1 :B_1 ,~… ∀ y_{k_i} :B_{k_i} ,~A_i'` and :math:`B_{k_i}` an inductive type. - -Now in the definition :math:`t_i`, if :math:`f_j` occurs then it should be applied to -at least :math:`k_j` arguments and the :math:`k_j`-th argument should be -syntactically recognized as structurally smaller than :math:`y_{k_i}`. - -The definition of being structurally smaller is a bit technical. One -needs first to define the notion of *recursive arguments of a -constructor*. For an inductive definition :math:`\ind{r}{Γ_I}{Γ_C}`, if the -type of a constructor :math:`c` has the form -:math:`∀ p_1 :P_1 ,~… ∀ p_r :P_r,~∀ x_1:T_1,~… ∀ x_m :T_m,~(I_j~p_1 … p_r~t_1 … t_s )`, -then the recursive -arguments will correspond to :math:`T_i` in which one of the :math:`I_l` occurs. - -The main rules for being structurally smaller are the following. -Given a variable :math:`y` of an inductively defined type in a declaration -:math:`\ind{r}{Γ_I}{Γ_C}` where :math:`Γ_I` is :math:`[I_1 :A_1 ;~…;~I_k :A_k]`, and :math:`Γ_C` is -:math:`[c_1 :C_1 ;~…;~c_n :C_n ]`, the terms structurally smaller than :math:`y` are: - - -+ :math:`(t~u)` and :math:`λ x:U .~t` when :math:`t` is structurally smaller than :math:`y`. -+ :math:`\case(c,P,f_1 … f_n)` when each :math:`f_i` is structurally smaller than :math:`y`. - If :math:`c` is :math:`y` or is structurally smaller than :math:`y`, its type is an inductive - type :math:`I_p` part of the inductive definition corresponding to :math:`y`. - Each :math:`f_i` corresponds to a type of constructor - :math:`C_q ≡ ∀ p_1 :P_1 ,~…,∀ p_r :P_r ,~∀ y_1 :B_1 ,~… ∀ y_m :B_m ,~(I_p~p_1 … p_r~t_1 … t_s )` - and can consequently be written :math:`λ y_1 :B_1' .~… λ y_m :B_m'.~g_i`. (:math:`B_i'` is - obtained from :math:`B_i` by substituting parameters for variables) the variables - :math:`y_j` occurring in :math:`g_i` corresponding to recursive arguments :math:`B_i` (the - ones in which one of the :math:`I_l` occurs) are structurally smaller than :math:`y`. - - -The following definitions are correct, we enter them using the :cmd:`Fixpoint` -command and show the internal representation. - -.. example:: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (plus p m) - end. - - Print plus. - Fixpoint lgth (A:Set) (l:list A) {struct l} : nat := - match l with - | nil _ => O - | cons _ a l' => S (lgth A l') - end. - Print lgth. - Fixpoint sizet (t:tree) : nat := let (f) := t in S (sizef f) - with sizef (f:forest) : nat := - match f with - | emptyf => O - | consf t f => plus (sizet t) (sizef f) - end. - Print sizet. - -.. _Reduction-rule: - -Reduction rule -++++++++++++++ - -Let :math:`F` be the set of declarations: -:math:`f_1 /k_1 :A_1 :=t_1 …f_n /k_n :A_n:=t_n`. -The reduction for fixpoints is: - -.. math:: - (\Fix~f_i \{F\}~a_1 …a_{k_i}) ~\triangleright_ι~ \subst{t_i}{f_k}{\Fix~f_k \{F\}}_{k=1… n} ~a_1 … a_{k_i} - -when :math:`a_{k_i}` starts with a constructor. This last restriction is needed -in order to keep strong normalization and corresponds to the reduction -for primitive recursive operators. The following reductions are now -possible: - -.. math:: - :nowrap: - - \begin{eqnarray*} - \plus~(\nS~(\nS~\nO))~(\nS~\nO)~& \trii & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\ - & \trii & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\ - & \trii & \nS~(\nS~(\nS~\nO))\\ - \end{eqnarray*} - -.. _Mutual-induction: - -**Mutual induction** - -The principles of mutual induction can be automatically generated -using the Scheme command described in Section :ref:`proofschemes-induction-principles`. diff --git a/doc/sphinx/language/core/inductive.rst b/doc/sphinx/language/core/inductive.rst new file mode 100644 index 0000000000..678374e83e --- /dev/null +++ b/doc/sphinx/language/core/inductive.rst @@ -0,0 +1,1210 @@ +.. _inductive-definitions: + +Inductive Definitions +------------------------- + +Formally, we can represent any *inductive definition* as +:math:`\ind{p}{Γ_I}{Γ_C}` where: + ++ :math:`Γ_I` determines the names and types of inductive types; ++ :math:`Γ_C` determines the names and types of constructors of these + inductive types; ++ :math:`p` determines the number of parameters of these inductive types. + + +These inductive definitions, together with global assumptions and +global definitions, then form the global environment. Additionally, +for any :math:`p` there always exists :math:`Γ_P =[a_1 :A_1 ;~…;~a_p :A_p ]` such that +each :math:`T` in :math:`(t:T)∈Γ_I \cup Γ_C` can be written as: :math:`∀Γ_P , T'` where :math:`Γ_P` is +called the *context of parameters*. Furthermore, we must have that +each :math:`T` in :math:`(t:T)∈Γ_I` can be written as: :math:`∀Γ_P,∀Γ_{\mathit{Arr}(t)}, S` where +:math:`Γ_{\mathit{Arr}(t)}` is called the *Arity* of the inductive type :math:`t` and :math:`S` is called +the sort of the inductive type :math:`t` (not to be confused with :math:`\Sort` which is the set of sorts). + +.. example:: + + The declaration for parameterized lists is: + + .. math:: + \ind{1}{[\List:\Set→\Set]}{\left[\begin{array}{rcl} + \Nil & : & ∀ A:\Set,~\List~A \\ + \cons & : & ∀ A:\Set,~A→ \List~A→ \List~A + \end{array} + \right]} + + which corresponds to the result of the |Coq| declaration: + + .. coqtop:: in + + Inductive list (A:Set) : Set := + | nil : list A + | cons : A -> list A -> list A. + +.. example:: + + The declaration for a mutual inductive definition of tree and forest + is: + + .. math:: + \ind{0}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]} + {\left[\begin{array}{rcl} + \node &:& \forest → \tree\\ + \emptyf &:& \forest\\ + \consf &:& \tree → \forest → \forest\\ + \end{array}\right]} + + which corresponds to the result of the |Coq| declaration: + + .. coqtop:: in + + Inductive tree : Set := + | node : forest -> tree + with forest : Set := + | emptyf : forest + | consf : tree -> forest -> forest. + +.. example:: + + The declaration for a mutual inductive definition of even and odd is: + + .. math:: + \ind{0}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\ + \odd&:&\nat → \Prop \end{array}\right]} + {\left[\begin{array}{rcl} + \evenO &:& \even~0\\ + \evenS &:& ∀ n,~\odd~n → \even~(\nS~n)\\ + \oddS &:& ∀ n,~\even~n → \odd~(\nS~n) + \end{array}\right]} + + which corresponds to the result of the |Coq| declaration: + + .. coqtop:: in + + Inductive even : nat -> Prop := + | even_O : even 0 + | even_S : forall n, odd n -> even (S n) + with odd : nat -> Prop := + | odd_S : forall n, even n -> odd (S n). + + + +.. _Types-of-inductive-objects: + +Types of inductive objects +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We have to give the type of constants in a global environment :math:`E` which +contains an inductive definition. + +.. inference:: Ind + + \WFE{Γ} + \ind{p}{Γ_I}{Γ_C} ∈ E + (a:A)∈Γ_I + --------------------- + E[Γ] ⊢ a : A + +.. inference:: Constr + + \WFE{Γ} + \ind{p}{Γ_I}{Γ_C} ∈ E + (c:C)∈Γ_C + --------------------- + E[Γ] ⊢ c : C + +.. example:: + + Provided that our environment :math:`E` contains inductive definitions we showed before, + these two inference rules above enable us to conclude that: + + .. math:: + \begin{array}{l} + E[Γ] ⊢ \even : \nat→\Prop\\ + E[Γ] ⊢ \odd : \nat→\Prop\\ + E[Γ] ⊢ \evenO : \even~\nO\\ + E[Γ] ⊢ \evenS : ∀ n:\nat,~\odd~n → \even~(\nS~n)\\ + E[Γ] ⊢ \oddS : ∀ n:\nat,~\even~n → \odd~(\nS~n) + \end{array} + + + + +.. _Well-formed-inductive-definitions: + +Well-formed inductive definitions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We cannot accept any inductive definition because some of them lead +to inconsistent systems. We restrict ourselves to definitions which +satisfy a syntactic criterion of positivity. Before giving the formal +rules, we need a few definitions: + +Arity of a given sort ++++++++++++++++++++++ + +A type :math:`T` is an *arity of sort* :math:`s` if it converts to the sort :math:`s` or to a +product :math:`∀ x:T,~U` with :math:`U` an arity of sort :math:`s`. + +.. example:: + + :math:`A→\Set` is an arity of sort :math:`\Set`. :math:`∀ A:\Prop,~A→ \Prop` is an arity of sort + :math:`\Prop`. + + +Arity ++++++ +A type :math:`T` is an *arity* if there is a :math:`s∈ \Sort` such that :math:`T` is an arity of +sort :math:`s`. + + +.. example:: + + :math:`A→ \Set` and :math:`∀ A:\Prop,~A→ \Prop` are arities. + + +Type of constructor ++++++++++++++++++++ +We say that :math:`T` is a *type of constructor of* :math:`I` in one of the following +two cases: + ++ :math:`T` is :math:`(I~t_1 … t_n )` ++ :math:`T` is :math:`∀ x:U,~T'` where :math:`T'` is also a type of constructor of :math:`I` + +.. example:: + + :math:`\nat` and :math:`\nat→\nat` are types of constructor of :math:`\nat`. + :math:`∀ A:\Type,~\List~A` and :math:`∀ A:\Type,~A→\List~A→\List~A` are types of constructor of :math:`\List`. + +.. _positivity: + +Positivity Condition +++++++++++++++++++++ + +The type of constructor :math:`T` will be said to *satisfy the positivity +condition* for a constant :math:`X` in the following cases: + ++ :math:`T=(X~t_1 … t_n )` and :math:`X` does not occur free in any :math:`t_i` ++ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` + satisfies the positivity condition for :math:`X`. + +Strict positivity ++++++++++++++++++ + +The constant :math:`X` *occurs strictly positively* in :math:`T` in the following +cases: + + ++ :math:`X` does not occur in :math:`T` ++ :math:`T` converts to :math:`(X~t_1 … t_n )` and :math:`X` does not occur in any of :math:`t_i` ++ :math:`T` converts to :math:`∀ x:U,~V` and :math:`X` does not occur in type :math:`U` but occurs + strictly positively in type :math:`V` ++ :math:`T` converts to :math:`(I~a_1 … a_m~t_1 … t_p )` where :math:`I` is the name of an + inductive definition of the form + + .. math:: + \ind{m}{I:A}{c_1 :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_1 ;~…;~c_n :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_n} + + (in particular, it is + not mutually defined and it has :math:`m` parameters) and :math:`X` does not occur in + any of the :math:`t_i`, and the (instantiated) types of constructor + :math:`\subst{C_i}{p_j}{a_j}_{j=1… m}` of :math:`I` satisfy the nested positivity condition for :math:`X` + +Nested Positivity ++++++++++++++++++ + +The type of constructor :math:`T` of :math:`I` *satisfies the nested positivity +condition* for a constant :math:`X` in the following cases: + ++ :math:`T=(I~b_1 … b_m~u_1 … u_p)`, :math:`I` is an inductive type with :math:`m` + parameters and :math:`X` does not occur in any :math:`u_i` ++ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` + satisfies the nested positivity condition for :math:`X` + + +.. example:: + + For instance, if one considers the following variant of a tree type + branching over the natural numbers: + + .. coqtop:: in + + Inductive nattree (A:Type) : Type := + | leaf : nattree A + | natnode : A -> (nat -> nattree A) -> nattree A. + + Then every instantiated constructor of ``nattree A`` satisfies the nested positivity + condition for ``nattree``: + + + Type ``nattree A`` of constructor ``leaf`` satisfies the positivity condition for + ``nattree`` because ``nattree`` does not appear in any (real) arguments of the + type of that constructor (primarily because ``nattree`` does not have any (real) + arguments) ... (bullet 1) + + + Type ``A → (nat → nattree A) → nattree A`` of constructor ``natnode`` satisfies the + positivity condition for ``nattree`` because: + + - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 1) + + - ``nattree`` occurs only strictly positively in ``nat → nattree A`` ... (bullet 3 + 2) + + - ``nattree`` satisfies the positivity condition for ``nattree A`` ... (bullet 1) + +.. _Correctness-rules: + +Correctness rules ++++++++++++++++++ + +We shall now describe the rules allowing the introduction of a new +inductive definition. + +Let :math:`E` be a global environment and :math:`Γ_P`, :math:`Γ_I`, :math:`Γ_C` be contexts +such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k]`, and +:math:`Γ_C` is :math:`[c_1:∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n ]`. Then + +.. inference:: W-Ind + + \WFE{Γ_P} + (E[Γ_I ;Γ_P ] ⊢ C_i : s_{q_i} )_{i=1… n} + ------------------------------------------ + \WF{E;~\ind{p}{Γ_I}{Γ_C}}{} + + +provided that the following side conditions hold: + + + :math:`k>0` and all of :math:`I_j` and :math:`c_i` are distinct names for :math:`j=1… k` and :math:`i=1… n`, + + :math:`p` is the number of parameters of :math:`\ind{p}{Γ_I}{Γ_C}` and :math:`Γ_P` is the + context of parameters, + + for :math:`j=1… k` we have that :math:`A_j` is an arity of sort :math:`s_j` and :math:`I_j ∉ E`, + + for :math:`i=1… n` we have that :math:`C_i` is a type of constructor of :math:`I_{q_i}` which + satisfies the positivity condition for :math:`I_1 … I_k` and :math:`c_i ∉ E`. + +One can remark that there is a constraint between the sort of the +arity of the inductive type and the sort of the type of its +constructors which will always be satisfied for the impredicative +sorts :math:`\SProp` and :math:`\Prop` but may fail to define +inductive type on sort :math:`\Set` and generate constraints +between universes for inductive types in the Type hierarchy. + + +.. example:: + + It is well known that the existential quantifier can be encoded as an + inductive definition. The following declaration introduces the + second-order existential quantifier :math:`∃ X.P(X)`. + + .. coqtop:: in + + Inductive exProp (P:Prop->Prop) : Prop := + | exP_intro : forall X:Prop, P X -> exProp P. + + The same definition on :math:`\Set` is not allowed and fails: + + .. coqtop:: all + + Fail Inductive exSet (P:Set->Prop) : Set := + exS_intro : forall X:Set, P X -> exSet P. + + It is possible to declare the same inductive definition in the + universe :math:`\Type`. The :g:`exType` inductive definition has type + :math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT}_{\kw{intro}}` + has type :math:`\Type(k)` with :math:`kProp) : Type := + exT_intro : forall X:Type, P X -> exType P. + + +.. example:: Negative occurrence (first example) + + The following inductive definition is rejected because it does not + satisfy the positivity condition: + + .. coqtop:: all + + Fail Inductive I : Prop := not_I_I (not_I : I -> False) : I. + + If we were to accept such definition, we could derive a + contradiction from it (we can test this by disabling the + :flag:`Positivity Checking` flag): + + .. coqtop:: none + + Unset Positivity Checking. + Inductive I : Prop := not_I_I (not_I : I -> False) : I. + Set Positivity Checking. + + .. coqtop:: all + + Definition I_not_I : I -> ~ I := fun i => + match i with not_I_I not_I => not_I end. + + .. coqtop:: in + + Lemma contradiction : False. + Proof. + enough (I /\ ~ I) as [] by contradiction. + split. + - apply not_I_I. + intro. + now apply I_not_I. + - intro. + now apply I_not_I. + Qed. + +.. example:: Negative occurrence (second example) + + Here is another example of an inductive definition which is + rejected because it does not satify the positivity condition: + + .. coqtop:: all + + Fail Inductive Lam := lam (_ : Lam -> Lam). + + Again, if we were to accept it, we could derive a contradiction + (this time through a non-terminating recursive function): + + .. coqtop:: none + + Unset Positivity Checking. + Inductive Lam := lam (_ : Lam -> Lam). + Set Positivity Checking. + + .. coqtop:: all + + Fixpoint infinite_loop l : False := + match l with lam x => infinite_loop (x l) end. + + Check infinite_loop (lam (@id Lam)) : False. + +.. example:: Non strictly positive occurrence + + It is less obvious why inductive type definitions with occurences + that are positive but not strictly positive are harmful. + We will see that in presence of an impredicative type they + are unsound: + + .. coqtop:: all + + Fail Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. + + If we were to accept this definition we could derive a contradiction + by creating an injective function from :math:`A → \Prop` to :math:`A`. + + This function is defined by composing the injective constructor of + the type :math:`A` with the function :math:`λx. λz. z = x` injecting + any type :math:`T` into :math:`T → \Prop`. + + .. coqtop:: none + + Unset Positivity Checking. + Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. + Set Positivity Checking. + + .. coqtop:: all + + Definition f (x: A -> Prop): A := introA (fun z => z = x). + + .. coqtop:: in + + Lemma f_inj: forall x y, f x = f y -> x = y. + Proof. + unfold f; intros ? ? H; injection H. + set (F := fun z => z = y); intro HF. + symmetry; replace (y = x) with (F y). + + unfold F; reflexivity. + + rewrite <- HF; reflexivity. + Qed. + + The type :math:`A → \Prop` can be understood as the powerset + of the type :math:`A`. To derive a contradiction from the + injective function :math:`f` we use Cantor's classic diagonal + argument. + + .. coqtop:: all + + Definition d: A -> Prop := fun x => exists s, x = f s /\ ~s x. + Definition fd: A := f d. + + .. coqtop:: in + + Lemma cantor: (d fd) <-> ~(d fd). + Proof. + split. + + intros [s [H1 H2]]; unfold fd in H1. + replace d with s. + * assumption. + * apply f_inj; congruence. + + intro; exists d; tauto. + Qed. + + Lemma bad: False. + Proof. + pose cantor; tauto. + Qed. + + This derivation was first presented by Thierry Coquand and Christine + Paulin in :cite:`CP90`. + +.. _Template-polymorphism: + +Template polymorphism ++++++++++++++++++++++ + +Inductive types can be made polymorphic over the universes introduced by +their parameters in :math:`\Type`, if the minimal inferred sort of the +inductive declarations either mention some of those parameter universes +or is computed to be :math:`\Prop` or :math:`\Set`. + +If :math:`A` is an arity of some sort and :math:`s` is a sort, we write :math:`A_{/s}` +for the arity obtained from :math:`A` by replacing its sort with :math:`s`. +Especially, if :math:`A` is well-typed in some global environment and local +context, then :math:`A_{/s}` is typable by typability of all products in the +Calculus of Inductive Constructions. The following typing rule is +added to the theory. + +Let :math:`\ind{p}{Γ_I}{Γ_C}` be an inductive definition. Let +:math:`Γ_P = [p_1 :P_1 ;~…;~p_p :P_p ]` be its context of parameters, +:math:`Γ_I = [I_1:∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k ]` its context of definitions and +:math:`Γ_C = [c_1 :∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n]` its context of constructors, +with :math:`c_i` a constructor of :math:`I_{q_i}`. Let :math:`m ≤ p` be the length of the +longest prefix of parameters such that the :math:`m` first arguments of all +occurrences of all :math:`I_j` in all :math:`C_k` (even the occurrences in the +hypotheses of :math:`C_k`) are exactly applied to :math:`p_1 … p_m` (:math:`m` is the number +of *recursively uniform parameters* and the :math:`p−m` remaining parameters +are the *recursively non-uniform parameters*). Let :math:`q_1 , …, q_r`, with +:math:`0≤ r≤ m`, be a (possibly) partial instantiation of the recursively +uniform parameters of :math:`Γ_P`. We have: + +.. inference:: Ind-Family + + \left\{\begin{array}{l} + \ind{p}{Γ_I}{Γ_C} \in E\\ + (E[] ⊢ q_l : P'_l)_{l=1\ldots r}\\ + (E[] ⊢ P'_l ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1})_{l=1\ldots r}\\ + 1 \leq j \leq k + \end{array} + \right. + ----------------------------- + E[] ⊢ I_j~q_1 … q_r :∀ [p_{r+1} :P_{r+1} ;~…;~p_p :P_p], (A_j)_{/s_j} + +provided that the following side conditions hold: + + + :math:`Γ_{P′}` is the context obtained from :math:`Γ_P` by replacing each :math:`P_l` that is + an arity with :math:`P_l'` for :math:`1≤ l ≤ r` (notice that :math:`P_l` arity implies :math:`P_l'` + arity since :math:`E[] ⊢ P_l' ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1}`); + + there are sorts :math:`s_i`, for :math:`1 ≤ i ≤ k` such that, for + :math:`Γ_{I'} = [I_1 :∀ Γ_{P'} ,(A_1)_{/s_1} ;~…;~I_k :∀ Γ_{P'} ,(A_k)_{/s_k}]` + we have :math:`(E[Γ_{I′} ;Γ_{P′}] ⊢ C_i : s_{q_i})_{i=1… n}` ; + + the sorts :math:`s_i` are all introduced by the inductive + declaration and have no universe constraints beside being greater + than or equal to :math:`\Prop`, and such that all + eliminations, to :math:`\Prop`, :math:`\Set` and :math:`\Type(j)`, + are allowed (see Section :ref:`Destructors`). + + +Notice that if :math:`I_j~q_1 … q_r` is typable using the rules **Ind-Const** and +**App**, then it is typable using the rule **Ind-Family**. Conversely, the +extended theory is not stronger than the theory without **Ind-Family**. We +get an equiconsistency result by mapping each :math:`\ind{p}{Γ_I}{Γ_C}` +occurring into a given derivation into as many different inductive +types and constructors as the number of different (partial) +replacements of sorts, needed for this derivation, in the parameters +that are arities (this is possible because :math:`\ind{p}{Γ_I}{Γ_C}` well-formed +implies that :math:`\ind{p}{Γ_{I'}}{Γ_{C'}}` is well-formed and has the +same allowed eliminations, where :math:`Γ_{I′}` is defined as above and +:math:`Γ_{C′} = [c_1 :∀ Γ_{P′} ,C_1 ;~…;~c_n :∀ Γ_{P′} ,C_n ]`). That is, the changes in the +types of each partial instance :math:`q_1 … q_r` can be characterized by the +ordered sets of arity sorts among the types of parameters, and to each +signature is associated a new inductive definition with fresh names. +Conversion is preserved as any (partial) instance :math:`I_j~q_1 … q_r` or +:math:`C_i~q_1 … q_r` is mapped to the names chosen in the specific instance of +:math:`\ind{p}{Γ_I}{Γ_C}`. + +.. warning:: + + The restriction that sorts are introduced by the inductive + declaration prevents inductive types declared in sections to be + template-polymorphic on universes introduced previously in the + section: they cannot parameterize over the universes introduced with + section variables that become parameters at section closing time, as + these may be shared with other definitions from the same section + which can impose constraints on them. + +.. flag:: Auto Template Polymorphism + + This flag, enabled by default, makes every inductive type declared + at level :math:`\Type` (without annotations or hiding it behind a + definition) template polymorphic if possible. + + This can be prevented using the :attr:`universes(notemplate)` + attribute. + + Template polymorphism and full universe polymorphism (see Chapter + :ref:`polymorphicuniverses`) are incompatible, so if the latter is + enabled (through the :flag:`Universe Polymorphism` flag or the + :attr:`universes(polymorphic)` attribute) it will prevail over + automatic template polymorphism. + +.. warn:: Automatically declaring @ident as template polymorphic. + + Warning ``auto-template`` can be used (it is off by default) to + find which types are implicitly declared template polymorphic by + :flag:`Auto Template Polymorphism`. + + An inductive type can be forced to be template polymorphic using + the :attr:`universes(template)` attribute: in this case, the + warning is not emitted. + +.. attr:: universes(template) + + This attribute can be used to explicitly declare an inductive type + as template polymorphic, whether the :flag:`Auto Template + Polymorphism` flag is on or off. + + .. exn:: template and polymorphism not compatible + + This attribute cannot be used in a full universe polymorphic + context, i.e. if the :flag:`Universe Polymorphism` flag is on or + if the :attr:`universes(polymorphic)` attribute is used. + + .. exn:: Ill-formed template inductive declaration: not polymorphic on any universe. + + The attribute was used but the inductive definition does not + satisfy the criterion to be template polymorphic. + +.. attr:: universes(notemplate) + + This attribute can be used to prevent an inductive type to be + template polymorphic, even if the :flag:`Auto Template + Polymorphism` flag is on. + +In practice, the rule **Ind-Family** is used by |Coq| only when all the +inductive types of the inductive definition are declared with an arity +whose sort is in the Type hierarchy. Then, the polymorphism is over +the parameters whose type is an arity of sort in the Type hierarchy. +The sorts :math:`s_j` are chosen canonically so that each :math:`s_j` is minimal with +respect to the hierarchy :math:`\Prop ⊂ \Set_p ⊂ \Type` where :math:`\Set_p` is predicative +:math:`\Set`. More precisely, an empty or small singleton inductive definition +(i.e. an inductive definition of which all inductive types are +singleton – see Section :ref:`Destructors`) is set in :math:`\Prop`, a small non-singleton +inductive type is set in :math:`\Set` (even in case :math:`\Set` is impredicative – see +Section The-Calculus-of-Inductive-Construction-with-impredicative-Set_), +and otherwise in the Type hierarchy. + +Note that the side-condition about allowed elimination sorts in the rule +**Ind-Family** avoids to recompute the allowed elimination sorts at each +instance of a pattern matching (see Section :ref:`Destructors`). As an +example, let us consider the following definition: + +.. example:: + + .. coqtop:: in + + Inductive option (A:Type) : Type := + | None : option A + | Some : A -> option A. + +As the definition is set in the Type hierarchy, it is used +polymorphically over its parameters whose types are arities of a sort +in the Type hierarchy. Here, the parameter :math:`A` has this property, hence, +if :g:`option` is applied to a type in :math:`\Set`, the result is in :math:`\Set`. Note that +if :g:`option` is applied to a type in :math:`\Prop`, then, the result is not set in +:math:`\Prop` but in :math:`\Set` still. This is because :g:`option` is not a singleton type +(see Section :ref:`Destructors`) and it would lose the elimination to :math:`\Set` and :math:`\Type` +if set in :math:`\Prop`. + +.. example:: + + .. coqtop:: all + + Check (fun A:Set => option A). + Check (fun A:Prop => option A). + +Here is another example. + +.. example:: + + .. coqtop:: in + + Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. + +As :g:`prod` is a singleton type, it will be in :math:`\Prop` if applied twice to +propositions, in :math:`\Set` if applied twice to at least one type in :math:`\Set` and +none in :math:`\Type`, and in :math:`\Type` otherwise. In all cases, the three kind of +eliminations schemes are allowed. + +.. example:: + + .. coqtop:: all + + Check (fun A:Set => prod A). + Check (fun A:Prop => prod A A). + Check (fun (A:Prop) (B:Set) => prod A B). + Check (fun (A:Type) (B:Prop) => prod A B). + +.. note:: + Template polymorphism used to be called “sort-polymorphism of + inductive types” before universe polymorphism + (see Chapter :ref:`polymorphicuniverses`) was introduced. + + +.. _Destructors: + +Destructors +~~~~~~~~~~~~~~~~~ + +The specification of inductive definitions with arities and +constructors is quite natural. But we still have to say how to use an +object in an inductive type. + +This problem is rather delicate. There are actually several different +ways to do that. Some of them are logically equivalent but not always +equivalent from the computational point of view or from the user point +of view. + +From the computational point of view, we want to be able to define a +function whose domain is an inductively defined type by using a +combination of case analysis over the possible constructors of the +object and recursion. + +Because we need to keep a consistent theory and also we prefer to keep +a strongly normalizing reduction, we cannot accept any sort of +recursion (even terminating). So the basic idea is to restrict +ourselves to primitive recursive functions and functionals. + +For instance, assuming a parameter :math:`A:\Set` exists in the local context, +we want to build a function :math:`\length` of type :math:`\List~A → \nat` which computes +the length of the list, such that :math:`(\length~(\Nil~A)) = \nO` and +:math:`(\length~(\cons~A~a~l)) = (\nS~(\length~l))`. +We want these equalities to be +recognized implicitly and taken into account in the conversion rule. + +From the logical point of view, we have built a type family by giving +a set of constructors. We want to capture the fact that we do not have +any other way to build an object in this type. So when trying to prove +a property about an object :math:`m` in an inductive type it is enough +to enumerate all the cases where :math:`m` starts with a different +constructor. + +In case the inductive definition is effectively a recursive one, we +want to capture the extra property that we have built the smallest +fixed point of this recursive equation. This says that we are only +manipulating finite objects. This analysis provides induction +principles. For instance, in order to prove +:math:`∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l))` it is enough to prove: + + ++ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~(\length~(\Nil~A)))` ++ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` + :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\length~(\cons~A~a~l)))` + + +which given the conversion equalities satisfied by :math:`\length` is the same +as proving: + + ++ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~\nO)` ++ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` + :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\nS~(\length~l)))` + + +One conceptually simple way to do that, following the basic scheme +proposed by Martin-Löf in his Intuitionistic Type Theory, is to +introduce for each inductive definition an elimination operator. At +the logical level it is a proof of the usual induction principle and +at the computational level it implements a generic operator for doing +primitive recursion over the structure. + +But this operator is rather tedious to implement and use. We choose in +this version of |Coq| to factorize the operator for primitive recursion +into two more primitive operations as was first suggested by Th. +Coquand in :cite:`Coq92`. One is the definition by pattern matching. The +second one is a definition by guarded fixpoints. + + +.. _match-construction: + +The match ... with ... end construction ++++++++++++++++++++++++++++++++++++++++ + +The basic idea of this operator is that we have an object :math:`m` in an +inductive type :math:`I` and we want to prove a property which possibly +depends on :math:`m`. For this, it is enough to prove the property for +:math:`m = (c_i~u_1 … u_{p_i} )` for each constructor of :math:`I`. +The |Coq| term for this proof +will be written: + +.. math:: + \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend + +In this expression, if :math:`m` eventually happens to evaluate to +:math:`(c_i~u_1 … u_{p_i})` then the expression will behave as specified in its :math:`i`-th branch +and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are replaced by the +:math:`u_1 … u_{p_i}` according to the ι-reduction. + +Actually, for type checking a :math:`\Match…\with…\kwend` expression we also need +to know the predicate :math:`P` to be proved by case analysis. In the general +case where :math:`I` is an inductively defined :math:`n`-ary relation, :math:`P` is a predicate +over :math:`n+1` arguments: the :math:`n` first ones correspond to the arguments of :math:`I` +(parameters excluded), and the last one corresponds to object :math:`m`. |Coq| +can sometimes infer this predicate but sometimes not. The concrete +syntax for describing this predicate uses the :math:`\as…\In…\return` +construction. For instance, let us assume that :math:`I` is an unary predicate +with one parameter and one argument. The predicate is made explicit +using the syntax: + +.. math:: + \Match~m~\as~x~\In~I~\_~a~\return~P~\with~ + (c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … + | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend + +The :math:`\as` part can be omitted if either the result type does not depend +on :math:`m` (non-dependent elimination) or :math:`m` is a variable (in this case, :math:`m` +can occur in :math:`P` where it is considered a bound variable). The :math:`\In` part +can be omitted if the result type does not depend on the arguments +of :math:`I`. Note that the arguments of :math:`I` corresponding to parameters *must* +be :math:`\_`, because the result type is not generalized to all possible +values of the parameters. The other arguments of :math:`I` (sometimes called +indices in the literature) have to be variables (:math:`a` above) and these +variables can occur in :math:`P`. The expression after :math:`\In` must be seen as an +*inductive type pattern*. Notice that expansion of implicit arguments +and notations apply to this pattern. For the purpose of presenting the +inference rules, we use a more compact notation: + +.. math:: + \case(m,(λ a x . P), λ x_{11} ... x_{1p_1} . f_1~| … |~λ x_{n1} ...x_{np_n} . f_n ) + + +.. _Allowed-elimination-sorts: + +**Allowed elimination sorts.** An important question for building the typing rule for :math:`\Match` is what +can be the type of :math:`λ a x . P` with respect to the type of :math:`m`. If :math:`m:I` +and :math:`I:A` and :math:`λ a x . P : B` then by :math:`[I:A|B]` we mean that one can use +:math:`λ a x . P` with :math:`m` in the above match-construct. + + +.. _cic_notations: + +**Notations.** The :math:`[I:A|B]` is defined as the smallest relation satisfying the +following rules: We write :math:`[I|B]` for :math:`[I:A|B]` where :math:`A` is the type of :math:`I`. + +The case of inductive types in sorts :math:`\Set` or :math:`\Type` is simple. +There is no restriction on the sort of the predicate to be eliminated. + +.. inference:: Prod + + [(I~x):A′|B′] + ----------------------- + [I:∀ x:A,~A′|∀ x:A,~B′] + + +.. inference:: Set & Type + + s_1 ∈ \{\Set,\Type(j)\} + s_2 ∈ \Sort + ---------------- + [I:s_1 |I→ s_2 ] + + +The case of Inductive definitions of sort :math:`\Prop` is a bit more +complicated, because of our interpretation of this sort. The only +harmless allowed eliminations, are the ones when predicate :math:`P` +is also of sort :math:`\Prop` or is of the morally smaller sort +:math:`\SProp`. + +.. inference:: Prop + + s ∈ \{\SProp,\Prop\} + -------------------- + [I:\Prop|I→s] + + +:math:`\Prop` is the type of logical propositions, the proofs of properties :math:`P` in +:math:`\Prop` could not be used for computation and are consequently ignored by +the extraction mechanism. Assume :math:`A` and :math:`B` are two propositions, and the +logical disjunction :math:`A ∨ B` is defined inductively by: + +.. example:: + + .. coqtop:: in + + Inductive or (A B:Prop) : Prop := + or_introl : A -> or A B | or_intror : B -> or A B. + + +The following definition which computes a boolean value by case over +the proof of :g:`or A B` is not accepted: + +.. example:: + + .. coqtop:: all + + Fail Definition choice (A B: Prop) (x:or A B) := + match x with or_introl _ _ a => true | or_intror _ _ b => false end. + +From the computational point of view, the structure of the proof of +:g:`(or A B)` in this term is needed for computing the boolean value. + +In general, if :math:`I` has type :math:`\Prop` then :math:`P` cannot have type :math:`I→\Set`, because +it will mean to build an informative proof of type :math:`(P~m)` doing a case +analysis over a non-computational object that will disappear in the +extracted program. But the other way is safe with respect to our +interpretation we can have :math:`I` a computational object and :math:`P` a +non-computational one, it just corresponds to proving a logical property +of a computational object. + +In the same spirit, elimination on :math:`P` of type :math:`I→\Type` cannot be allowed +because it trivially implies the elimination on :math:`P` of type :math:`I→ \Set` by +cumulativity. It also implies that there are two proofs of the same +property which are provably different, contradicting the +proof-irrelevance property which is sometimes a useful axiom: + +.. example:: + + .. coqtop:: all + + Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y. + +The elimination of an inductive type of sort :math:`\Prop` on a predicate +:math:`P` of type :math:`I→ \Type` leads to a paradox when applied to impredicative +inductive definition like the second-order existential quantifier +:g:`exProp` defined above, because it gives access to the two projections on +this type. + + +.. _Empty-and-singleton-elimination: + +**Empty and singleton elimination.** There are special inductive definitions in +:math:`\Prop` for which more eliminations are allowed. + +.. inference:: Prop-extended + + I~\kw{is an empty or singleton definition} + s ∈ \Sort + ------------------------------------- + [I:\Prop|I→ s] + +A *singleton definition* has only one constructor and all the +arguments of this constructor have type :math:`\Prop`. In that case, there is a +canonical way to interpret the informative extraction on an object in +that type, such that the elimination on any sort :math:`s` is legal. Typical +examples are the conjunction of non-informative propositions and the +equality. If there is a hypothesis :math:`h:a=b` in the local context, it can +be used for rewriting not only in logical propositions but also in any +type. + +.. example:: + + .. coqtop:: all + + Print eq_rec. + Require Extraction. + Extraction eq_rec. + +An empty definition has no constructors, in that case also, +elimination on any sort is allowed. + +.. _Eliminaton-for-SProp: + +Inductive types in :math:`\SProp` must have no constructors (i.e. be +empty) to be eliminated to produce relevant values. + +Note that thanks to proof irrelevance elimination functions can be +produced for other types, for instance the elimination for a unit type +is the identity. + +.. _Type-of-branches: + +**Type of branches.** +Let :math:`c` be a term of type :math:`C`, we assume :math:`C` is a type of constructor for an +inductive type :math:`I`. Let :math:`P` be a term that represents the property to be +proved. We assume :math:`r` is the number of parameters and :math:`s` is the number of +arguments. + +We define a new type :math:`\{c:C\}^P` which represents the type of the branch +corresponding to the :math:`c:C` constructor. + +.. math:: + \begin{array}{ll} + \{c:(I~q_1\ldots q_r\ t_1 \ldots t_s)\}^P &\equiv (P~t_1\ldots ~t_s~c) \\ + \{c:∀ x:T,~C\}^P &\equiv ∀ x:T,~\{(c~x):C\}^P + \end{array} + +We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:`c`. + + +.. example:: + + The following term in concrete syntax:: + + match t as l return P' with + | nil _ => t1 + | cons _ hd tl => t2 + end + + + can be represented in abstract syntax as + + .. math:: + \case(t,P,f_1 | f_2 ) + + where + + .. math:: + :nowrap: + + \begin{eqnarray*} + P & = & λ l.~P^\prime\\ + f_1 & = & t_1\\ + f_2 & = & λ (hd:\nat).~λ (tl:\List~\nat).~t_2 + \end{eqnarray*} + + According to the definition: + + .. math:: + \{(\Nil~\nat)\}^P ≡ \{(\Nil~\nat) : (\List~\nat)\}^P ≡ (P~(\Nil~\nat)) + + .. math:: + + \begin{array}{rl} + \{(\cons~\nat)\}^P & ≡\{(\cons~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\ + & ≡∀ n:\nat,~\{(\cons~\nat~n) : (\List~\nat→\List~\nat)\}^P \\ + & ≡∀ n:\nat,~∀ l:\List~\nat,~\{(\cons~\nat~n~l) : (\List~\nat)\}^P \\ + & ≡∀ n:\nat,~∀ l:\List~\nat,~(P~(\cons~\nat~n~l)). + \end{array} + + Given some :math:`P` then :math:`\{(\Nil~\nat)\}^P` represents the expected type of :math:`f_1`, + and :math:`\{(\cons~\nat)\}^P` represents the expected type of :math:`f_2`. + + +.. _Typing-rule: + +**Typing rule.** +Our very general destructor for inductive definition enjoys the +following typing rule + +.. inference:: match + + \begin{array}{l} + E[Γ] ⊢ c : (I~q_1 … q_r~t_1 … t_s ) \\ + E[Γ] ⊢ P : B \\ + [(I~q_1 … q_r)|B] \\ + (E[Γ] ⊢ f_i : \{(c_{p_i}~q_1 … q_r)\}^P)_{i=1… l} + \end{array} + ------------------------------------------------ + E[Γ] ⊢ \case(c,P,f_1 |… |f_l ) : (P~t_1 … t_s~c) + +provided :math:`I` is an inductive type in a +definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;~…;~c_n :C_n ]` and +:math:`c_{p_1} … c_{p_l}` are the only constructors of :math:`I`. + + + +.. example:: + + Below is a typing rule for the term shown in the previous example: + + .. inference:: list example + + \begin{array}{l} + E[Γ] ⊢ t : (\List ~\nat) \\ + E[Γ] ⊢ P : B \\ + [(\List ~\nat)|B] \\ + E[Γ] ⊢ f_1 : \{(\Nil ~\nat)\}^P \\ + E[Γ] ⊢ f_2 : \{(\cons ~\nat)\}^P + \end{array} + ------------------------------------------------ + E[Γ] ⊢ \case(t,P,f_1 |f_2 ) : (P~t) + + +.. _Definition-of-ι-reduction: + +**Definition of ι-reduction.** +We still have to define the ι-reduction in the general case. + +An ι-redex is a term of the following form: + +.. math:: + \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) + +with :math:`c_{p_i}` the :math:`i`-th constructor of the inductive type :math:`I` with :math:`r` +parameters. + +The ι-contraction of this term is :math:`(f_i~a_1 … a_m )` leading to the +general reduction rule: + +.. math:: + \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) \triangleright_ι (f_i~a_1 … a_m ) + + +.. _Fixpoint-definitions: + +Fixpoint definitions +~~~~~~~~~~~~~~~~~~~~ + +The second operator for elimination is fixpoint definition. This +fixpoint may involve several mutually recursive definitions. The basic +concrete syntax for a recursive set of mutually recursive declarations +is (with :math:`Γ_i` contexts): + +.. math:: + \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n + + +The terms are obtained by projections from this set of declarations +and are written + +.. math:: + \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n~\for~f_i + +In the inference rules, we represent such a term by + +.. math:: + \Fix~f_i\{f_1 :A_1':=t_1' … f_n :A_n':=t_n'\} + +with :math:`t_i'` (resp. :math:`A_i'`) representing the term :math:`t_i` abstracted (resp. +generalized) with respect to the bindings in the context :math:`Γ_i`, namely +:math:`t_i'=λ Γ_i . t_i` and :math:`A_i'=∀ Γ_i , A_i`. + + +Typing rule ++++++++++++ + +The typing rule is the expected one for a fixpoint. + +.. inference:: Fix + + (E[Γ] ⊢ A_i : s_i )_{i=1… n} + (E[Γ;~f_1 :A_1 ;~…;~f_n :A_n ] ⊢ t_i : A_i )_{i=1… n} + ------------------------------------------------------- + E[Γ] ⊢ \Fix~f_i\{f_1 :A_1 :=t_1 … f_n :A_n :=t_n \} : A_i + + +Any fixpoint definition cannot be accepted because non-normalizing +terms allow proofs of absurdity. The basic scheme of recursion that +should be allowed is the one needed for defining primitive recursive +functionals. In that case the fixpoint enjoys a special syntactic +restriction, namely one of the arguments belongs to an inductive type, +the function starts with a case analysis and recursive calls are done +on variables coming from patterns and representing subterms. For +instance in the case of natural numbers, a proof of the induction +principle of type + +.. math:: + ∀ P:\nat→\Prop,~(P~\nO)→(∀ n:\nat,~(P~n)→(P~(\nS~n)))→ ∀ n:\nat,~(P~n) + +can be represented by the term: + +.. math:: + \begin{array}{l} + λ P:\nat→\Prop.~λ f:(P~\nO).~λ g:(∀ n:\nat,~(P~n)→(P~(\nS~n))).\\ + \Fix~h\{h:∀ n:\nat,~(P~n):=λ n:\nat.~\case(n,P,f | λp:\nat.~(g~p~(h~p)))\} + \end{array} + +Before accepting a fixpoint definition as being correctly typed, we +check that the definition is “guarded”. A precise analysis of this +notion can be found in :cite:`Gim94`. The first stage is to precise on which +argument the fixpoint will be decreasing. The type of this argument +should be an inductive type. For doing this, the syntax of +fixpoints is extended and becomes + +.. math:: + \Fix~f_i\{f_1/k_1 :A_1:=t_1 … f_n/k_n :A_n:=t_n\} + + +where :math:`k_i` are positive integers. Each :math:`k_i` represents the index of +parameter of :math:`f_i`, on which :math:`f_i` is decreasing. Each :math:`A_i` should be a +type (reducible to a term) starting with at least :math:`k_i` products +:math:`∀ y_1 :B_1 ,~… ∀ y_{k_i} :B_{k_i} ,~A_i'` and :math:`B_{k_i}` an inductive type. + +Now in the definition :math:`t_i`, if :math:`f_j` occurs then it should be applied to +at least :math:`k_j` arguments and the :math:`k_j`-th argument should be +syntactically recognized as structurally smaller than :math:`y_{k_i}`. + +The definition of being structurally smaller is a bit technical. One +needs first to define the notion of *recursive arguments of a +constructor*. For an inductive definition :math:`\ind{r}{Γ_I}{Γ_C}`, if the +type of a constructor :math:`c` has the form +:math:`∀ p_1 :P_1 ,~… ∀ p_r :P_r,~∀ x_1:T_1,~… ∀ x_m :T_m,~(I_j~p_1 … p_r~t_1 … t_s )`, +then the recursive +arguments will correspond to :math:`T_i` in which one of the :math:`I_l` occurs. + +The main rules for being structurally smaller are the following. +Given a variable :math:`y` of an inductively defined type in a declaration +:math:`\ind{r}{Γ_I}{Γ_C}` where :math:`Γ_I` is :math:`[I_1 :A_1 ;~…;~I_k :A_k]`, and :math:`Γ_C` is +:math:`[c_1 :C_1 ;~…;~c_n :C_n ]`, the terms structurally smaller than :math:`y` are: + + ++ :math:`(t~u)` and :math:`λ x:U .~t` when :math:`t` is structurally smaller than :math:`y`. ++ :math:`\case(c,P,f_1 … f_n)` when each :math:`f_i` is structurally smaller than :math:`y`. + If :math:`c` is :math:`y` or is structurally smaller than :math:`y`, its type is an inductive + type :math:`I_p` part of the inductive definition corresponding to :math:`y`. + Each :math:`f_i` corresponds to a type of constructor + :math:`C_q ≡ ∀ p_1 :P_1 ,~…,∀ p_r :P_r ,~∀ y_1 :B_1 ,~… ∀ y_m :B_m ,~(I_p~p_1 … p_r~t_1 … t_s )` + and can consequently be written :math:`λ y_1 :B_1' .~… λ y_m :B_m'.~g_i`. (:math:`B_i'` is + obtained from :math:`B_i` by substituting parameters for variables) the variables + :math:`y_j` occurring in :math:`g_i` corresponding to recursive arguments :math:`B_i` (the + ones in which one of the :math:`I_l` occurs) are structurally smaller than :math:`y`. + + +The following definitions are correct, we enter them using the :cmd:`Fixpoint` +command and show the internal representation. + +.. example:: + + .. coqtop:: all + + Fixpoint plus (n m:nat) {struct n} : nat := + match n with + | O => m + | S p => S (plus p m) + end. + + Print plus. + Fixpoint lgth (A:Set) (l:list A) {struct l} : nat := + match l with + | nil _ => O + | cons _ a l' => S (lgth A l') + end. + Print lgth. + Fixpoint sizet (t:tree) : nat := let (f) := t in S (sizef f) + with sizef (f:forest) : nat := + match f with + | emptyf => O + | consf t f => plus (sizet t) (sizef f) + end. + Print sizet. + +.. _Reduction-rule: + +Reduction rule +++++++++++++++ + +Let :math:`F` be the set of declarations: +:math:`f_1 /k_1 :A_1 :=t_1 …f_n /k_n :A_n:=t_n`. +The reduction for fixpoints is: + +.. math:: + (\Fix~f_i \{F\}~a_1 …a_{k_i}) ~\triangleright_ι~ \subst{t_i}{f_k}{\Fix~f_k \{F\}}_{k=1… n} ~a_1 … a_{k_i} + +when :math:`a_{k_i}` starts with a constructor. This last restriction is needed +in order to keep strong normalization and corresponds to the reduction +for primitive recursive operators. The following reductions are now +possible: + +.. math:: + :nowrap: + + \begin{eqnarray*} + \plus~(\nS~(\nS~\nO))~(\nS~\nO)~& \trii & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\ + & \trii & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\ + & \trii & \nS~(\nS~(\nS~\nO))\\ + \end{eqnarray*} + +.. _Mutual-induction: + +**Mutual induction** + +The principles of mutual induction can be automatically generated +using the Scheme command described in Section :ref:`proofschemes-induction-principles`. -- cgit v1.2.3 From b1617e188d71e8a27f2888b9e3106373170448d4 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 23:35:34 +0200 Subject: Extract conversion rules from CIC. --- doc/sphinx/language/cic.rst | 1892 ------------------------------------------- 1 file changed, 1892 deletions(-) diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst index b125d21a3c..0f27b65107 100644 --- a/doc/sphinx/language/cic.rst +++ b/doc/sphinx/language/cic.rst @@ -1,417 +1,3 @@ -.. _calculusofinductiveconstructions: - - -Calculus of Inductive Constructions -==================================== - -The underlying formal language of |Coq| is a *Calculus of Inductive -Constructions* (|Cic|) whose inference rules are presented in this -chapter. The history of this formalism as well as pointers to related -work are provided in a separate chapter; see *Credits*. - - -.. _The-terms: - -The terms -------------- - -The expressions of the |Cic| are *terms* and all terms have a *type*. -There are types for functions (or programs), there are atomic types -(especially datatypes)... but also types for proofs and types for the -types themselves. Especially, any object handled in the formalism must -belong to a type. For instance, universal quantification is relative -to a type and takes the form “*for all x of type* :math:`T`, :math:`P`”. The expression -“:math:`x` *of type* :math:`T`” is written “:math:`x:T`”. Informally, “:math:`x:T`” can be thought as -“:math:`x` *belongs to* :math:`T`”. - -The types of types are called :gdef:`sort`\s. Types and sorts are themselves terms -so that terms, types and sorts are all components of a common -syntactic language of terms which is described in Section :ref:`terms`. But -first, we describe sorts. - - -.. _Sorts: - -Sorts -~~~~~~~~~~~ - -All sorts have a type and there is an infinite well-founded typing -hierarchy of sorts whose base sorts are :math:`\SProp`, :math:`\Prop` -and :math:`\Set`. - -The sort :math:`\Prop` intends to be the type of logical propositions. If :math:`M` is a -logical proposition then it denotes the class of terms representing -proofs of :math:`M`. An object :math:`m` belonging to :math:`M` witnesses the fact that :math:`M` is -provable. An object of type :math:`\Prop` is called a proposition. - -The sort :math:`\SProp` is like :math:`\Prop` but the propositions in -:math:`\SProp` are known to have irrelevant proofs (all proofs are -equal). Objects of type :math:`\SProp` are called strict propositions. -See :ref:`sprop` for information about using -:math:`\SProp`, and :cite:`Gilbert:POPL2019` for meta theoretical -considerations. - -The sort :math:`\Set` intends to be the type of small sets. This includes data -types such as booleans and naturals, but also products, subsets, and -function types over these data types. - -:math:`\SProp`, :math:`\Prop` and :math:`\Set` themselves can be manipulated as ordinary terms. -Consequently they also have a type. Because assuming simply that :math:`\Set` -has type :math:`\Set` leads to an inconsistent theory :cite:`Coq86`, the language of -|Cic| has infinitely many sorts. There are, in addition to the base sorts, -a hierarchy of universes :math:`\Type(i)` for any integer :math:`i ≥ 1`. - -Like :math:`\Set`, all of the sorts :math:`\Type(i)` contain small sets such as -booleans, natural numbers, as well as products, subsets and function -types over small sets. But, unlike :math:`\Set`, they also contain large sets, -namely the sorts :math:`\Set` and :math:`\Type(j)` for :math:`j u` - in |Coq| concrete syntax) is a term. This is a notation for the - λ-abstraction of λ-calculus :cite:`Bar81`. The term :math:`λ x:T .~u` is a function - which maps elements of :math:`T` to the expression :math:`u`. -#. if :math:`t` and :math:`u` are terms then :math:`(t~u)` is a term - (:g:`t u` in |Coq| concrete - syntax). The term :math:`(t~u)` reads as “:math:`t` applied to :math:`u`”. -#. if :math:`x` is a variable, and :math:`t`, :math:`T` and :math:`u` are - terms then :math:`\letin{x}{t:T}{u}` is - a term which denotes the term :math:`u` where the variable :math:`x` is locally bound - to :math:`t` of type :math:`T`. This stands for the common “let-in” construction of - functional programs such as ML or Scheme. - - - -.. _Free-variables: - -**Free variables.** -The notion of free variables is defined as usual. In the expressions -:math:`λx:T.~U` and :math:`∀ x:T,~U` the occurrences of :math:`x` in :math:`U` are bound. - - -.. _Substitution: - -**Substitution.** -The notion of substituting a term :math:`t` to free occurrences of a variable -:math:`x` in a term :math:`u` is defined as usual. The resulting term is written -:math:`\subst{u}{x}{t}`. - - -.. _The-logical-vs-programming-readings: - -**The logical vs programming readings.** -The constructions of the |Cic| can be used to express both logical and -programming notions, accordingly to the Curry-Howard correspondence -between proofs and programs, and between propositions and types -:cite:`Cur58,How80,Bru72`. - -For instance, let us assume that :math:`\nat` is the type of natural numbers -with zero element written :math:`0` and that :g:`True` is the always true -proposition. Then :math:`→` is used both to denote :math:`\nat→\nat` which is the type -of functions from :math:`\nat` to :math:`\nat`, to denote True→True which is an -implicative proposition, to denote :math:`\nat →\Prop` which is the type of -unary predicates over the natural numbers, etc. - -Let us assume that ``mult`` is a function of type :math:`\nat→\nat→\nat` and ``eqnat`` a -predicate of type :math:`\nat→\nat→ \Prop`. The λ-abstraction can serve to build -“ordinary” functions as in :math:`λ x:\nat.~(\kw{mult}~x~x)` (i.e. -:g:`fun x:nat => mult x x` -in |Coq| notation) but may build also predicates over the natural -numbers. For instance :math:`λ x:\nat.~(\kw{eqnat}~x~0)` -(i.e. :g:`fun x:nat => eqnat x 0` -in |Coq| notation) will represent the predicate of one variable :math:`x` which -asserts the equality of :math:`x` with :math:`0`. This predicate has type -:math:`\nat → \Prop` -and it can be applied to any expression of type :math:`\nat`, say :math:`t`, to give an -object :math:`P~t` of type :math:`\Prop`, namely a proposition. - -Furthermore :g:`forall x:nat, P x` will represent the type of functions -which associate to each natural number :math:`n` an object of type :math:`(P~n)` and -consequently represent the type of proofs of the formula “:math:`∀ x.~P(x)`”. - - -.. _Typing-rules: - -Typing rules ----------------- - -As objects of type theory, terms are subjected to *type discipline*. -The well typing of a term depends on a global environment and a local -context. - - -.. _Local-context: - -**Local context.** -A *local context* is an ordered list of *local declarations* of names -which we call *variables*. The declaration of some variable :math:`x` is -either a *local assumption*, written :math:`x:T` (:math:`T` is a type) or a *local -definition*, written :math:`x:=t:T`. We use brackets to write local contexts. -A typical example is :math:`[x:T;~y:=u:U;~z:V]`. Notice that the variables -declared in a local context must be distinct. If :math:`Γ` is a local context -that declares some :math:`x`, we -write :math:`x ∈ Γ`. By writing :math:`(x:T) ∈ Γ` we mean that either :math:`x:T` is an -assumption in :math:`Γ` or that there exists some :math:`t` such that :math:`x:=t:T` is a -definition in :math:`Γ`. If :math:`Γ` defines some :math:`x:=t:T`, we also write :math:`(x:=t:T) ∈ Γ`. -For the rest of the chapter, :math:`Γ::(y:T)` denotes the local context :math:`Γ` -enriched with the local assumption :math:`y:T`. Similarly, :math:`Γ::(y:=t:T)` denotes -the local context :math:`Γ` enriched with the local definition :math:`(y:=t:T)`. The -notation :math:`[]` denotes the empty local context. By :math:`Γ_1 ; Γ_2` we mean -concatenation of the local context :math:`Γ_1` and the local context :math:`Γ_2`. - - -.. _Global-environment: - -**Global environment.** -A *global environment* is an ordered list of *global declarations*. -Global declarations are either *global assumptions* or *global -definitions*, but also declarations of inductive objects. Inductive -objects themselves declare both inductive or coinductive types and -constructors (see Section :ref:`inductive-definitions`). - -A *global assumption* will be represented in the global environment as -:math:`(c:T)` which assumes the name :math:`c` to be of some type :math:`T`. A *global -definition* will be represented in the global environment as :math:`c:=t:T` -which defines the name :math:`c` to have value :math:`t` and type :math:`T`. We shall call -such names *constants*. For the rest of the chapter, the :math:`E;~c:T` denotes -the global environment :math:`E` enriched with the global assumption :math:`c:T`. -Similarly, :math:`E;~c:=t:T` denotes the global environment :math:`E` enriched with the -global definition :math:`(c:=t:T)`. - -The rules for inductive definitions (see Section -:ref:`inductive-definitions`) have to be considered as assumption -rules to which the following definitions apply: if the name :math:`c` -is declared in :math:`E`, we write :math:`c ∈ E` and if :math:`c:T` or -:math:`c:=t:T` is declared in :math:`E`, we write :math:`(c : T) ∈ E`. - - -.. _Typing-rules2: - -**Typing rules.** -In the following, we define simultaneously two judgments. The first -one :math:`\WTEG{t}{T}` means the term :math:`t` is well-typed and has type :math:`T` in the -global environment :math:`E` and local context :math:`Γ`. The second judgment :math:`\WFE{Γ}` -means that the global environment :math:`E` is well-formed and the local -context :math:`Γ` is a valid local context in this global environment. - -A term :math:`t` is well typed in a global environment :math:`E` iff -there exists a local context :math:`\Gamma` and a term :math:`T` such -that the judgment :math:`\WTEG{t}{T}` can be derived from the -following rules. - -.. inference:: W-Empty - - --------- - \WF{[]}{} - -.. inference:: W-Local-Assum - - \WTEG{T}{s} - s \in \Sort - x \not\in \Gamma % \cup E - ------------------------- - \WFE{\Gamma::(x:T)} - -.. inference:: W-Local-Def - - \WTEG{t}{T} - x \not\in \Gamma % \cup E - ------------------------- - \WFE{\Gamma::(x:=t:T)} - -.. inference:: W-Global-Assum - - \WTE{}{T}{s} - s \in \Sort - c \notin E - ------------ - \WF{E;~c:T}{} - -.. inference:: W-Global-Def - - \WTE{}{t}{T} - c \notin E - --------------- - \WF{E;~c:=t:T}{} - -.. inference:: Ax-SProp - - \WFE{\Gamma} - ---------------------- - \WTEG{\SProp}{\Type(1)} - -.. inference:: Ax-Prop - - \WFE{\Gamma} - ---------------------- - \WTEG{\Prop}{\Type(1)} - -.. inference:: Ax-Set - - \WFE{\Gamma} - --------------------- - \WTEG{\Set}{\Type(1)} - -.. inference:: Ax-Type - - \WFE{\Gamma} - --------------------------- - \WTEG{\Type(i)}{\Type(i+1)} - -.. inference:: Var - - \WFE{\Gamma} - (x:T) \in \Gamma~~\mbox{or}~~(x:=t:T) \in \Gamma~\mbox{for some $t$} - -------------------------------------------------------------------- - \WTEG{x}{T} - -.. inference:: Const - - \WFE{\Gamma} - (c:T) \in E~~\mbox{or}~~(c:=t:T) \in E~\mbox{for some $t$} - ---------------------------------------------------------- - \WTEG{c}{T} - -.. inference:: Prod-SProp - - \WTEG{T}{s} - s \in {\Sort} - \WTE{\Gamma::(x:T)}{U}{\SProp} - ----------------------------- - \WTEG{\forall~x:T,U}{\SProp} - -.. inference:: Prod-Prop - - \WTEG{T}{s} - s \in \Sort - \WTE{\Gamma::(x:T)}{U}{\Prop} - ----------------------------- - \WTEG{∀ x:T,~U}{\Prop} - -.. inference:: Prod-Set - - \WTEG{T}{s} - s \in \{\SProp, \Prop, \Set\} - \WTE{\Gamma::(x:T)}{U}{\Set} - ---------------------------- - \WTEG{∀ x:T,~U}{\Set} - -.. inference:: Prod-Type - - \WTEG{T}{s} - s \in \{\SProp, \Type{i}\} - \WTE{\Gamma::(x:T)}{U}{\Type(i)} - -------------------------------- - \WTEG{∀ x:T,~U}{\Type(i)} - -.. inference:: Lam - - \WTEG{∀ x:T,~U}{s} - \WTE{\Gamma::(x:T)}{t}{U} - ------------------------------------ - \WTEG{λ x:T\mto t}{∀ x:T,~U} - -.. inference:: App - - \WTEG{t}{∀ x:U,~T} - \WTEG{u}{U} - ------------------------------ - \WTEG{(t\ u)}{\subst{T}{x}{u}} - -.. inference:: Let - - \WTEG{t}{T} - \WTE{\Gamma::(x:=t:T)}{u}{U} - ----------------------------------------- - \WTEG{\letin{x}{t:T}{u}}{\subst{U}{x}{t}} - - - -.. note:: - - **Prod-Prop** and **Prod-Set** typing-rules make sense if we consider the - semantic difference between :math:`\Prop` and :math:`\Set`: - - + All values of a type that has a sort :math:`\Set` are extractable. - + No values of a type that has a sort :math:`\Prop` are extractable. - - - -.. note:: - We may have :math:`\letin{x}{t:T}{u}` well-typed without having - :math:`((λ x:T.~u)~t)` well-typed (where :math:`T` is a type of - :math:`t`). This is because the value :math:`t` associated to - :math:`x` may be used in a conversion rule - (see Section :ref:`Conversion-rules`). - - .. _Conversion-rules: Conversion rules @@ -624,1481 +210,3 @@ and we have The convertibility relation allows introducing a new typing rule which says that two convertible well-formed types have the same inhabitants. - - -.. _subtyping-rules: - -Subtyping rules -------------------- - -At the moment, we did not take into account one rule between universes -which says that any term in a universe of index :math:`i` is also a term in -the universe of index :math:`i+1` (this is the *cumulativity* rule of |Cic|). -This property extends the equivalence relation of convertibility into -a *subtyping* relation inductively defined by: - - -#. if :math:`E[Γ] ⊢ t =_{βδιζη} u` then :math:`E[Γ] ⊢ t ≤_{βδιζη} u`, -#. if :math:`i ≤ j` then :math:`E[Γ] ⊢ \Type(i) ≤_{βδιζη} \Type(j)`, -#. for any :math:`i`, :math:`E[Γ] ⊢ \Set ≤_{βδιζη} \Type(i)`, -#. :math:`E[Γ] ⊢ \Prop ≤_{βδιζη} \Set`, hence, by transitivity, - :math:`E[Γ] ⊢ \Prop ≤_{βδιζη} \Type(i)`, for any :math:`i` - (note: :math:`\SProp` is not related by cumulativity to any other term) -#. if :math:`E[Γ] ⊢ T =_{βδιζη} U` and - :math:`E[Γ::(x:T)] ⊢ T' ≤_{βδιζη} U'` then - :math:`E[Γ] ⊢ ∀x:T,~T′ ≤_{βδιζη} ∀ x:U,~U′`. -#. if :math:`\ind{p}{Γ_I}{Γ_C}` is a universe polymorphic and cumulative - (see Chapter :ref:`polymorphicuniverses`) inductive type (see below) - and - :math:`(t : ∀Γ_P ,∀Γ_{\mathit{Arr}(t)}, S)∈Γ_I` - and - :math:`(t' : ∀Γ_P' ,∀Γ_{\mathit{Arr}(t)}', S')∈Γ_I` - are two different instances of *the same* inductive type (differing only in - universe levels) with constructors - - .. math:: - [c_1 : ∀Γ_P ,∀ T_{1,1} … T_{1,n_1} ,~t~v_{1,1} … v_{1,m} ;~…;~ - c_k : ∀Γ_P ,∀ T_{k,1} … T_{k,n_k} ,~t~v_{k,1} … v_{k,m} ] - - and - - .. math:: - [c_1 : ∀Γ_P' ,∀ T_{1,1}' … T_{1,n_1}' ,~t'~v_{1,1}' … v_{1,m}' ;~…;~ - c_k : ∀Γ_P' ,∀ T_{k,1}' … T_{k,n_k}' ,~t'~v_{k,1}' … v_{k,m}' ] - - respectively then - - .. math:: - E[Γ] ⊢ t~w_1 … w_m ≤_{βδιζη} t'~w_1' … w_m' - - (notice that :math:`t` and :math:`t'` are both - fully applied, i.e., they have a sort as a type) if - - .. math:: - E[Γ] ⊢ w_i =_{βδιζη} w_i' - - for :math:`1 ≤ i ≤ m` and we have - - - .. math:: - E[Γ] ⊢ T_{i,j} ≤_{βδιζη} T_{i,j}' - - and - - .. math:: - E[Γ] ⊢ A_i ≤_{βδιζη} A_i' - - where :math:`Γ_{\mathit{Arr}(t)} = [a_1 : A_1 ;~ … ;~a_l : A_l ]` and - :math:`Γ_{\mathit{Arr}(t)}' = [a_1 : A_1';~ … ;~a_l : A_l']`. - - -The conversion rule up to subtyping is now exactly: - -.. inference:: Conv - - E[Γ] ⊢ U : s - E[Γ] ⊢ t : T - E[Γ] ⊢ T ≤_{βδιζη} U - -------------- - E[Γ] ⊢ t : U - - -.. _Normal-form: - -**Normal form**. A term which cannot be any more reduced is said to be in *normal -form*. There are several ways (or strategies) to apply the reduction -rules. Among them, we have to mention the *head reduction* which will -play an important role (see Chapter :ref:`tactics`). Any term :math:`t` can be written as -:math:`λ x_1 :T_1 .~… λ x_k :T_k .~(t_0~t_1 … t_n )` where :math:`t_0` is not an -application. We say then that :math:`t_0` is the *head of* :math:`t`. If we assume -that :math:`t_0` is :math:`λ x:T.~u_0` then one step of β-head reduction of :math:`t` is: - -.. math:: - λ x_1 :T_1 .~… λ x_k :T_k .~(λ x:T.~u_0~t_1 … t_n ) ~\triangleright~ - λ (x_1 :T_1 )…(x_k :T_k ).~(\subst{u_0}{x}{t_1}~t_2 … t_n ) - -Iterating the process of head reduction until the head of the reduced -term is no more an abstraction leads to the *β-head normal form* of :math:`t`: - -.. math:: - t \triangleright … \triangleright λ x_1 :T_1 .~…λ x_k :T_k .~(v~u_1 … u_m ) - -where :math:`v` is not an abstraction (nor an application). Note that the head -normal form must not be confused with the normal form since some :math:`u_i` -can be reducible. Similar notions of head-normal forms involving δ, ι -and ζ reductions or any combination of those can also be defined. - - -.. _inductive-definitions: - -Inductive Definitions -------------------------- - -Formally, we can represent any *inductive definition* as -:math:`\ind{p}{Γ_I}{Γ_C}` where: - -+ :math:`Γ_I` determines the names and types of inductive types; -+ :math:`Γ_C` determines the names and types of constructors of these - inductive types; -+ :math:`p` determines the number of parameters of these inductive types. - - -These inductive definitions, together with global assumptions and -global definitions, then form the global environment. Additionally, -for any :math:`p` there always exists :math:`Γ_P =[a_1 :A_1 ;~…;~a_p :A_p ]` such that -each :math:`T` in :math:`(t:T)∈Γ_I \cup Γ_C` can be written as: :math:`∀Γ_P , T'` where :math:`Γ_P` is -called the *context of parameters*. Furthermore, we must have that -each :math:`T` in :math:`(t:T)∈Γ_I` can be written as: :math:`∀Γ_P,∀Γ_{\mathit{Arr}(t)}, S` where -:math:`Γ_{\mathit{Arr}(t)}` is called the *Arity* of the inductive type :math:`t` and :math:`S` is called -the sort of the inductive type :math:`t` (not to be confused with :math:`\Sort` which is the set of sorts). - -.. example:: - - The declaration for parameterized lists is: - - .. math:: - \ind{1}{[\List:\Set→\Set]}{\left[\begin{array}{rcl} - \Nil & : & ∀ A:\Set,~\List~A \\ - \cons & : & ∀ A:\Set,~A→ \List~A→ \List~A - \end{array} - \right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive list (A:Set) : Set := - | nil : list A - | cons : A -> list A -> list A. - -.. example:: - - The declaration for a mutual inductive definition of tree and forest - is: - - .. math:: - \ind{0}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]} - {\left[\begin{array}{rcl} - \node &:& \forest → \tree\\ - \emptyf &:& \forest\\ - \consf &:& \tree → \forest → \forest\\ - \end{array}\right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive tree : Set := - | node : forest -> tree - with forest : Set := - | emptyf : forest - | consf : tree -> forest -> forest. - -.. example:: - - The declaration for a mutual inductive definition of even and odd is: - - .. math:: - \ind{0}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\ - \odd&:&\nat → \Prop \end{array}\right]} - {\left[\begin{array}{rcl} - \evenO &:& \even~0\\ - \evenS &:& ∀ n,~\odd~n → \even~(\nS~n)\\ - \oddS &:& ∀ n,~\even~n → \odd~(\nS~n) - \end{array}\right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive even : nat -> Prop := - | even_O : even 0 - | even_S : forall n, odd n -> even (S n) - with odd : nat -> Prop := - | odd_S : forall n, even n -> odd (S n). - - - -.. _Types-of-inductive-objects: - -Types of inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We have to give the type of constants in a global environment :math:`E` which -contains an inductive definition. - -.. inference:: Ind - - \WFE{Γ} - \ind{p}{Γ_I}{Γ_C} ∈ E - (a:A)∈Γ_I - --------------------- - E[Γ] ⊢ a : A - -.. inference:: Constr - - \WFE{Γ} - \ind{p}{Γ_I}{Γ_C} ∈ E - (c:C)∈Γ_C - --------------------- - E[Γ] ⊢ c : C - -.. example:: - - Provided that our environment :math:`E` contains inductive definitions we showed before, - these two inference rules above enable us to conclude that: - - .. math:: - \begin{array}{l} - E[Γ] ⊢ \even : \nat→\Prop\\ - E[Γ] ⊢ \odd : \nat→\Prop\\ - E[Γ] ⊢ \evenO : \even~\nO\\ - E[Γ] ⊢ \evenS : ∀ n:\nat,~\odd~n → \even~(\nS~n)\\ - E[Γ] ⊢ \oddS : ∀ n:\nat,~\even~n → \odd~(\nS~n) - \end{array} - - - - -.. _Well-formed-inductive-definitions: - -Well-formed inductive definitions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We cannot accept any inductive definition because some of them lead -to inconsistent systems. We restrict ourselves to definitions which -satisfy a syntactic criterion of positivity. Before giving the formal -rules, we need a few definitions: - -Arity of a given sort -+++++++++++++++++++++ - -A type :math:`T` is an *arity of sort* :math:`s` if it converts to the sort :math:`s` or to a -product :math:`∀ x:T,~U` with :math:`U` an arity of sort :math:`s`. - -.. example:: - - :math:`A→\Set` is an arity of sort :math:`\Set`. :math:`∀ A:\Prop,~A→ \Prop` is an arity of sort - :math:`\Prop`. - - -Arity -+++++ -A type :math:`T` is an *arity* if there is a :math:`s∈ \Sort` such that :math:`T` is an arity of -sort :math:`s`. - - -.. example:: - - :math:`A→ \Set` and :math:`∀ A:\Prop,~A→ \Prop` are arities. - - -Type of constructor -+++++++++++++++++++ -We say that :math:`T` is a *type of constructor of* :math:`I` in one of the following -two cases: - -+ :math:`T` is :math:`(I~t_1 … t_n )` -+ :math:`T` is :math:`∀ x:U,~T'` where :math:`T'` is also a type of constructor of :math:`I` - -.. example:: - - :math:`\nat` and :math:`\nat→\nat` are types of constructor of :math:`\nat`. - :math:`∀ A:\Type,~\List~A` and :math:`∀ A:\Type,~A→\List~A→\List~A` are types of constructor of :math:`\List`. - -.. _positivity: - -Positivity Condition -++++++++++++++++++++ - -The type of constructor :math:`T` will be said to *satisfy the positivity -condition* for a constant :math:`X` in the following cases: - -+ :math:`T=(X~t_1 … t_n )` and :math:`X` does not occur free in any :math:`t_i` -+ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` - satisfies the positivity condition for :math:`X`. - -Strict positivity -+++++++++++++++++ - -The constant :math:`X` *occurs strictly positively* in :math:`T` in the following -cases: - - -+ :math:`X` does not occur in :math:`T` -+ :math:`T` converts to :math:`(X~t_1 … t_n )` and :math:`X` does not occur in any of :math:`t_i` -+ :math:`T` converts to :math:`∀ x:U,~V` and :math:`X` does not occur in type :math:`U` but occurs - strictly positively in type :math:`V` -+ :math:`T` converts to :math:`(I~a_1 … a_m~t_1 … t_p )` where :math:`I` is the name of an - inductive definition of the form - - .. math:: - \ind{m}{I:A}{c_1 :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_1 ;~…;~c_n :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_n} - - (in particular, it is - not mutually defined and it has :math:`m` parameters) and :math:`X` does not occur in - any of the :math:`t_i`, and the (instantiated) types of constructor - :math:`\subst{C_i}{p_j}{a_j}_{j=1… m}` of :math:`I` satisfy the nested positivity condition for :math:`X` - -Nested Positivity -+++++++++++++++++ - -The type of constructor :math:`T` of :math:`I` *satisfies the nested positivity -condition* for a constant :math:`X` in the following cases: - -+ :math:`T=(I~b_1 … b_m~u_1 … u_p)`, :math:`I` is an inductive type with :math:`m` - parameters and :math:`X` does not occur in any :math:`u_i` -+ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` - satisfies the nested positivity condition for :math:`X` - - -.. example:: - - For instance, if one considers the following variant of a tree type - branching over the natural numbers: - - .. coqtop:: in - - Inductive nattree (A:Type) : Type := - | leaf : nattree A - | natnode : A -> (nat -> nattree A) -> nattree A. - - Then every instantiated constructor of ``nattree A`` satisfies the nested positivity - condition for ``nattree``: - - + Type ``nattree A`` of constructor ``leaf`` satisfies the positivity condition for - ``nattree`` because ``nattree`` does not appear in any (real) arguments of the - type of that constructor (primarily because ``nattree`` does not have any (real) - arguments) ... (bullet 1) - - + Type ``A → (nat → nattree A) → nattree A`` of constructor ``natnode`` satisfies the - positivity condition for ``nattree`` because: - - - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 1) - - - ``nattree`` occurs only strictly positively in ``nat → nattree A`` ... (bullet 3 + 2) - - - ``nattree`` satisfies the positivity condition for ``nattree A`` ... (bullet 1) - -.. _Correctness-rules: - -Correctness rules -+++++++++++++++++ - -We shall now describe the rules allowing the introduction of a new -inductive definition. - -Let :math:`E` be a global environment and :math:`Γ_P`, :math:`Γ_I`, :math:`Γ_C` be contexts -such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k]`, and -:math:`Γ_C` is :math:`[c_1:∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n ]`. Then - -.. inference:: W-Ind - - \WFE{Γ_P} - (E[Γ_I ;Γ_P ] ⊢ C_i : s_{q_i} )_{i=1… n} - ------------------------------------------ - \WF{E;~\ind{p}{Γ_I}{Γ_C}}{} - - -provided that the following side conditions hold: - - + :math:`k>0` and all of :math:`I_j` and :math:`c_i` are distinct names for :math:`j=1… k` and :math:`i=1… n`, - + :math:`p` is the number of parameters of :math:`\ind{p}{Γ_I}{Γ_C}` and :math:`Γ_P` is the - context of parameters, - + for :math:`j=1… k` we have that :math:`A_j` is an arity of sort :math:`s_j` and :math:`I_j ∉ E`, - + for :math:`i=1… n` we have that :math:`C_i` is a type of constructor of :math:`I_{q_i}` which - satisfies the positivity condition for :math:`I_1 … I_k` and :math:`c_i ∉ E`. - -One can remark that there is a constraint between the sort of the -arity of the inductive type and the sort of the type of its -constructors which will always be satisfied for the impredicative -sorts :math:`\SProp` and :math:`\Prop` but may fail to define -inductive type on sort :math:`\Set` and generate constraints -between universes for inductive types in the Type hierarchy. - - -.. example:: - - It is well known that the existential quantifier can be encoded as an - inductive definition. The following declaration introduces the - second-order existential quantifier :math:`∃ X.P(X)`. - - .. coqtop:: in - - Inductive exProp (P:Prop->Prop) : Prop := - | exP_intro : forall X:Prop, P X -> exProp P. - - The same definition on :math:`\Set` is not allowed and fails: - - .. coqtop:: all - - Fail Inductive exSet (P:Set->Prop) : Set := - exS_intro : forall X:Set, P X -> exSet P. - - It is possible to declare the same inductive definition in the - universe :math:`\Type`. The :g:`exType` inductive definition has type - :math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT}_{\kw{intro}}` - has type :math:`\Type(k)` with :math:`kProp) : Type := - exT_intro : forall X:Type, P X -> exType P. - - -.. example:: Negative occurrence (first example) - - The following inductive definition is rejected because it does not - satisfy the positivity condition: - - .. coqtop:: all - - Fail Inductive I : Prop := not_I_I (not_I : I -> False) : I. - - If we were to accept such definition, we could derive a - contradiction from it (we can test this by disabling the - :flag:`Positivity Checking` flag): - - .. coqtop:: none - - Unset Positivity Checking. - Inductive I : Prop := not_I_I (not_I : I -> False) : I. - Set Positivity Checking. - - .. coqtop:: all - - Definition I_not_I : I -> ~ I := fun i => - match i with not_I_I not_I => not_I end. - - .. coqtop:: in - - Lemma contradiction : False. - Proof. - enough (I /\ ~ I) as [] by contradiction. - split. - - apply not_I_I. - intro. - now apply I_not_I. - - intro. - now apply I_not_I. - Qed. - -.. example:: Negative occurrence (second example) - - Here is another example of an inductive definition which is - rejected because it does not satify the positivity condition: - - .. coqtop:: all - - Fail Inductive Lam := lam (_ : Lam -> Lam). - - Again, if we were to accept it, we could derive a contradiction - (this time through a non-terminating recursive function): - - .. coqtop:: none - - Unset Positivity Checking. - Inductive Lam := lam (_ : Lam -> Lam). - Set Positivity Checking. - - .. coqtop:: all - - Fixpoint infinite_loop l : False := - match l with lam x => infinite_loop (x l) end. - - Check infinite_loop (lam (@id Lam)) : False. - -.. example:: Non strictly positive occurrence - - It is less obvious why inductive type definitions with occurences - that are positive but not strictly positive are harmful. - We will see that in presence of an impredicative type they - are unsound: - - .. coqtop:: all - - Fail Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. - - If we were to accept this definition we could derive a contradiction - by creating an injective function from :math:`A → \Prop` to :math:`A`. - - This function is defined by composing the injective constructor of - the type :math:`A` with the function :math:`λx. λz. z = x` injecting - any type :math:`T` into :math:`T → \Prop`. - - .. coqtop:: none - - Unset Positivity Checking. - Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. - Set Positivity Checking. - - .. coqtop:: all - - Definition f (x: A -> Prop): A := introA (fun z => z = x). - - .. coqtop:: in - - Lemma f_inj: forall x y, f x = f y -> x = y. - Proof. - unfold f; intros ? ? H; injection H. - set (F := fun z => z = y); intro HF. - symmetry; replace (y = x) with (F y). - + unfold F; reflexivity. - + rewrite <- HF; reflexivity. - Qed. - - The type :math:`A → \Prop` can be understood as the powerset - of the type :math:`A`. To derive a contradiction from the - injective function :math:`f` we use Cantor's classic diagonal - argument. - - .. coqtop:: all - - Definition d: A -> Prop := fun x => exists s, x = f s /\ ~s x. - Definition fd: A := f d. - - .. coqtop:: in - - Lemma cantor: (d fd) <-> ~(d fd). - Proof. - split. - + intros [s [H1 H2]]; unfold fd in H1. - replace d with s. - * assumption. - * apply f_inj; congruence. - + intro; exists d; tauto. - Qed. - - Lemma bad: False. - Proof. - pose cantor; tauto. - Qed. - - This derivation was first presented by Thierry Coquand and Christine - Paulin in :cite:`CP90`. - -.. _Template-polymorphism: - -Template polymorphism -+++++++++++++++++++++ - -Inductive types can be made polymorphic over the universes introduced by -their parameters in :math:`\Type`, if the minimal inferred sort of the -inductive declarations either mention some of those parameter universes -or is computed to be :math:`\Prop` or :math:`\Set`. - -If :math:`A` is an arity of some sort and :math:`s` is a sort, we write :math:`A_{/s}` -for the arity obtained from :math:`A` by replacing its sort with :math:`s`. -Especially, if :math:`A` is well-typed in some global environment and local -context, then :math:`A_{/s}` is typable by typability of all products in the -Calculus of Inductive Constructions. The following typing rule is -added to the theory. - -Let :math:`\ind{p}{Γ_I}{Γ_C}` be an inductive definition. Let -:math:`Γ_P = [p_1 :P_1 ;~…;~p_p :P_p ]` be its context of parameters, -:math:`Γ_I = [I_1:∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k ]` its context of definitions and -:math:`Γ_C = [c_1 :∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n]` its context of constructors, -with :math:`c_i` a constructor of :math:`I_{q_i}`. Let :math:`m ≤ p` be the length of the -longest prefix of parameters such that the :math:`m` first arguments of all -occurrences of all :math:`I_j` in all :math:`C_k` (even the occurrences in the -hypotheses of :math:`C_k`) are exactly applied to :math:`p_1 … p_m` (:math:`m` is the number -of *recursively uniform parameters* and the :math:`p−m` remaining parameters -are the *recursively non-uniform parameters*). Let :math:`q_1 , …, q_r`, with -:math:`0≤ r≤ m`, be a (possibly) partial instantiation of the recursively -uniform parameters of :math:`Γ_P`. We have: - -.. inference:: Ind-Family - - \left\{\begin{array}{l} - \ind{p}{Γ_I}{Γ_C} \in E\\ - (E[] ⊢ q_l : P'_l)_{l=1\ldots r}\\ - (E[] ⊢ P'_l ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1})_{l=1\ldots r}\\ - 1 \leq j \leq k - \end{array} - \right. - ----------------------------- - E[] ⊢ I_j~q_1 … q_r :∀ [p_{r+1} :P_{r+1} ;~…;~p_p :P_p], (A_j)_{/s_j} - -provided that the following side conditions hold: - - + :math:`Γ_{P′}` is the context obtained from :math:`Γ_P` by replacing each :math:`P_l` that is - an arity with :math:`P_l'` for :math:`1≤ l ≤ r` (notice that :math:`P_l` arity implies :math:`P_l'` - arity since :math:`E[] ⊢ P_l' ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1}`); - + there are sorts :math:`s_i`, for :math:`1 ≤ i ≤ k` such that, for - :math:`Γ_{I'} = [I_1 :∀ Γ_{P'} ,(A_1)_{/s_1} ;~…;~I_k :∀ Γ_{P'} ,(A_k)_{/s_k}]` - we have :math:`(E[Γ_{I′} ;Γ_{P′}] ⊢ C_i : s_{q_i})_{i=1… n}` ; - + the sorts :math:`s_i` are all introduced by the inductive - declaration and have no universe constraints beside being greater - than or equal to :math:`\Prop`, and such that all - eliminations, to :math:`\Prop`, :math:`\Set` and :math:`\Type(j)`, - are allowed (see Section :ref:`Destructors`). - - -Notice that if :math:`I_j~q_1 … q_r` is typable using the rules **Ind-Const** and -**App**, then it is typable using the rule **Ind-Family**. Conversely, the -extended theory is not stronger than the theory without **Ind-Family**. We -get an equiconsistency result by mapping each :math:`\ind{p}{Γ_I}{Γ_C}` -occurring into a given derivation into as many different inductive -types and constructors as the number of different (partial) -replacements of sorts, needed for this derivation, in the parameters -that are arities (this is possible because :math:`\ind{p}{Γ_I}{Γ_C}` well-formed -implies that :math:`\ind{p}{Γ_{I'}}{Γ_{C'}}` is well-formed and has the -same allowed eliminations, where :math:`Γ_{I′}` is defined as above and -:math:`Γ_{C′} = [c_1 :∀ Γ_{P′} ,C_1 ;~…;~c_n :∀ Γ_{P′} ,C_n ]`). That is, the changes in the -types of each partial instance :math:`q_1 … q_r` can be characterized by the -ordered sets of arity sorts among the types of parameters, and to each -signature is associated a new inductive definition with fresh names. -Conversion is preserved as any (partial) instance :math:`I_j~q_1 … q_r` or -:math:`C_i~q_1 … q_r` is mapped to the names chosen in the specific instance of -:math:`\ind{p}{Γ_I}{Γ_C}`. - -.. warning:: - - The restriction that sorts are introduced by the inductive - declaration prevents inductive types declared in sections to be - template-polymorphic on universes introduced previously in the - section: they cannot parameterize over the universes introduced with - section variables that become parameters at section closing time, as - these may be shared with other definitions from the same section - which can impose constraints on them. - -.. flag:: Auto Template Polymorphism - - This flag, enabled by default, makes every inductive type declared - at level :math:`\Type` (without annotations or hiding it behind a - definition) template polymorphic if possible. - - This can be prevented using the :attr:`universes(notemplate)` - attribute. - - Template polymorphism and full universe polymorphism (see Chapter - :ref:`polymorphicuniverses`) are incompatible, so if the latter is - enabled (through the :flag:`Universe Polymorphism` flag or the - :attr:`universes(polymorphic)` attribute) it will prevail over - automatic template polymorphism. - -.. warn:: Automatically declaring @ident as template polymorphic. - - Warning ``auto-template`` can be used (it is off by default) to - find which types are implicitly declared template polymorphic by - :flag:`Auto Template Polymorphism`. - - An inductive type can be forced to be template polymorphic using - the :attr:`universes(template)` attribute: in this case, the - warning is not emitted. - -.. attr:: universes(template) - - This attribute can be used to explicitly declare an inductive type - as template polymorphic, whether the :flag:`Auto Template - Polymorphism` flag is on or off. - - .. exn:: template and polymorphism not compatible - - This attribute cannot be used in a full universe polymorphic - context, i.e. if the :flag:`Universe Polymorphism` flag is on or - if the :attr:`universes(polymorphic)` attribute is used. - - .. exn:: Ill-formed template inductive declaration: not polymorphic on any universe. - - The attribute was used but the inductive definition does not - satisfy the criterion to be template polymorphic. - -.. attr:: universes(notemplate) - - This attribute can be used to prevent an inductive type to be - template polymorphic, even if the :flag:`Auto Template - Polymorphism` flag is on. - -In practice, the rule **Ind-Family** is used by |Coq| only when all the -inductive types of the inductive definition are declared with an arity -whose sort is in the Type hierarchy. Then, the polymorphism is over -the parameters whose type is an arity of sort in the Type hierarchy. -The sorts :math:`s_j` are chosen canonically so that each :math:`s_j` is minimal with -respect to the hierarchy :math:`\Prop ⊂ \Set_p ⊂ \Type` where :math:`\Set_p` is predicative -:math:`\Set`. More precisely, an empty or small singleton inductive definition -(i.e. an inductive definition of which all inductive types are -singleton – see Section :ref:`Destructors`) is set in :math:`\Prop`, a small non-singleton -inductive type is set in :math:`\Set` (even in case :math:`\Set` is impredicative – see -Section The-Calculus-of-Inductive-Construction-with-impredicative-Set_), -and otherwise in the Type hierarchy. - -Note that the side-condition about allowed elimination sorts in the rule -**Ind-Family** avoids to recompute the allowed elimination sorts at each -instance of a pattern matching (see Section :ref:`Destructors`). As an -example, let us consider the following definition: - -.. example:: - - .. coqtop:: in - - Inductive option (A:Type) : Type := - | None : option A - | Some : A -> option A. - -As the definition is set in the Type hierarchy, it is used -polymorphically over its parameters whose types are arities of a sort -in the Type hierarchy. Here, the parameter :math:`A` has this property, hence, -if :g:`option` is applied to a type in :math:`\Set`, the result is in :math:`\Set`. Note that -if :g:`option` is applied to a type in :math:`\Prop`, then, the result is not set in -:math:`\Prop` but in :math:`\Set` still. This is because :g:`option` is not a singleton type -(see Section :ref:`Destructors`) and it would lose the elimination to :math:`\Set` and :math:`\Type` -if set in :math:`\Prop`. - -.. example:: - - .. coqtop:: all - - Check (fun A:Set => option A). - Check (fun A:Prop => option A). - -Here is another example. - -.. example:: - - .. coqtop:: in - - Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. - -As :g:`prod` is a singleton type, it will be in :math:`\Prop` if applied twice to -propositions, in :math:`\Set` if applied twice to at least one type in :math:`\Set` and -none in :math:`\Type`, and in :math:`\Type` otherwise. In all cases, the three kind of -eliminations schemes are allowed. - -.. example:: - - .. coqtop:: all - - Check (fun A:Set => prod A). - Check (fun A:Prop => prod A A). - Check (fun (A:Prop) (B:Set) => prod A B). - Check (fun (A:Type) (B:Prop) => prod A B). - -.. note:: - Template polymorphism used to be called “sort-polymorphism of - inductive types” before universe polymorphism - (see Chapter :ref:`polymorphicuniverses`) was introduced. - - -.. _Destructors: - -Destructors -~~~~~~~~~~~~~~~~~ - -The specification of inductive definitions with arities and -constructors is quite natural. But we still have to say how to use an -object in an inductive type. - -This problem is rather delicate. There are actually several different -ways to do that. Some of them are logically equivalent but not always -equivalent from the computational point of view or from the user point -of view. - -From the computational point of view, we want to be able to define a -function whose domain is an inductively defined type by using a -combination of case analysis over the possible constructors of the -object and recursion. - -Because we need to keep a consistent theory and also we prefer to keep -a strongly normalizing reduction, we cannot accept any sort of -recursion (even terminating). So the basic idea is to restrict -ourselves to primitive recursive functions and functionals. - -For instance, assuming a parameter :math:`A:\Set` exists in the local context, -we want to build a function :math:`\length` of type :math:`\List~A → \nat` which computes -the length of the list, such that :math:`(\length~(\Nil~A)) = \nO` and -:math:`(\length~(\cons~A~a~l)) = (\nS~(\length~l))`. -We want these equalities to be -recognized implicitly and taken into account in the conversion rule. - -From the logical point of view, we have built a type family by giving -a set of constructors. We want to capture the fact that we do not have -any other way to build an object in this type. So when trying to prove -a property about an object :math:`m` in an inductive type it is enough -to enumerate all the cases where :math:`m` starts with a different -constructor. - -In case the inductive definition is effectively a recursive one, we -want to capture the extra property that we have built the smallest -fixed point of this recursive equation. This says that we are only -manipulating finite objects. This analysis provides induction -principles. For instance, in order to prove -:math:`∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l))` it is enough to prove: - - -+ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~(\length~(\Nil~A)))` -+ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` - :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\length~(\cons~A~a~l)))` - - -which given the conversion equalities satisfied by :math:`\length` is the same -as proving: - - -+ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~\nO)` -+ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` - :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\nS~(\length~l)))` - - -One conceptually simple way to do that, following the basic scheme -proposed by Martin-Löf in his Intuitionistic Type Theory, is to -introduce for each inductive definition an elimination operator. At -the logical level it is a proof of the usual induction principle and -at the computational level it implements a generic operator for doing -primitive recursion over the structure. - -But this operator is rather tedious to implement and use. We choose in -this version of |Coq| to factorize the operator for primitive recursion -into two more primitive operations as was first suggested by Th. -Coquand in :cite:`Coq92`. One is the definition by pattern matching. The -second one is a definition by guarded fixpoints. - - -.. _match-construction: - -The match ... with ... end construction -+++++++++++++++++++++++++++++++++++++++ - -The basic idea of this operator is that we have an object :math:`m` in an -inductive type :math:`I` and we want to prove a property which possibly -depends on :math:`m`. For this, it is enough to prove the property for -:math:`m = (c_i~u_1 … u_{p_i} )` for each constructor of :math:`I`. -The |Coq| term for this proof -will be written: - -.. math:: - \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend - -In this expression, if :math:`m` eventually happens to evaluate to -:math:`(c_i~u_1 … u_{p_i})` then the expression will behave as specified in its :math:`i`-th branch -and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are replaced by the -:math:`u_1 … u_{p_i}` according to the ι-reduction. - -Actually, for type checking a :math:`\Match…\with…\kwend` expression we also need -to know the predicate :math:`P` to be proved by case analysis. In the general -case where :math:`I` is an inductively defined :math:`n`-ary relation, :math:`P` is a predicate -over :math:`n+1` arguments: the :math:`n` first ones correspond to the arguments of :math:`I` -(parameters excluded), and the last one corresponds to object :math:`m`. |Coq| -can sometimes infer this predicate but sometimes not. The concrete -syntax for describing this predicate uses the :math:`\as…\In…\return` -construction. For instance, let us assume that :math:`I` is an unary predicate -with one parameter and one argument. The predicate is made explicit -using the syntax: - -.. math:: - \Match~m~\as~x~\In~I~\_~a~\return~P~\with~ - (c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … - | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend - -The :math:`\as` part can be omitted if either the result type does not depend -on :math:`m` (non-dependent elimination) or :math:`m` is a variable (in this case, :math:`m` -can occur in :math:`P` where it is considered a bound variable). The :math:`\In` part -can be omitted if the result type does not depend on the arguments -of :math:`I`. Note that the arguments of :math:`I` corresponding to parameters *must* -be :math:`\_`, because the result type is not generalized to all possible -values of the parameters. The other arguments of :math:`I` (sometimes called -indices in the literature) have to be variables (:math:`a` above) and these -variables can occur in :math:`P`. The expression after :math:`\In` must be seen as an -*inductive type pattern*. Notice that expansion of implicit arguments -and notations apply to this pattern. For the purpose of presenting the -inference rules, we use a more compact notation: - -.. math:: - \case(m,(λ a x . P), λ x_{11} ... x_{1p_1} . f_1~| … |~λ x_{n1} ...x_{np_n} . f_n ) - - -.. _Allowed-elimination-sorts: - -**Allowed elimination sorts.** An important question for building the typing rule for :math:`\Match` is what -can be the type of :math:`λ a x . P` with respect to the type of :math:`m`. If :math:`m:I` -and :math:`I:A` and :math:`λ a x . P : B` then by :math:`[I:A|B]` we mean that one can use -:math:`λ a x . P` with :math:`m` in the above match-construct. - - -.. _cic_notations: - -**Notations.** The :math:`[I:A|B]` is defined as the smallest relation satisfying the -following rules: We write :math:`[I|B]` for :math:`[I:A|B]` where :math:`A` is the type of :math:`I`. - -The case of inductive types in sorts :math:`\Set` or :math:`\Type` is simple. -There is no restriction on the sort of the predicate to be eliminated. - -.. inference:: Prod - - [(I~x):A′|B′] - ----------------------- - [I:∀ x:A,~A′|∀ x:A,~B′] - - -.. inference:: Set & Type - - s_1 ∈ \{\Set,\Type(j)\} - s_2 ∈ \Sort - ---------------- - [I:s_1 |I→ s_2 ] - - -The case of Inductive definitions of sort :math:`\Prop` is a bit more -complicated, because of our interpretation of this sort. The only -harmless allowed eliminations, are the ones when predicate :math:`P` -is also of sort :math:`\Prop` or is of the morally smaller sort -:math:`\SProp`. - -.. inference:: Prop - - s ∈ \{\SProp,\Prop\} - -------------------- - [I:\Prop|I→s] - - -:math:`\Prop` is the type of logical propositions, the proofs of properties :math:`P` in -:math:`\Prop` could not be used for computation and are consequently ignored by -the extraction mechanism. Assume :math:`A` and :math:`B` are two propositions, and the -logical disjunction :math:`A ∨ B` is defined inductively by: - -.. example:: - - .. coqtop:: in - - Inductive or (A B:Prop) : Prop := - or_introl : A -> or A B | or_intror : B -> or A B. - - -The following definition which computes a boolean value by case over -the proof of :g:`or A B` is not accepted: - -.. example:: - - .. coqtop:: all - - Fail Definition choice (A B: Prop) (x:or A B) := - match x with or_introl _ _ a => true | or_intror _ _ b => false end. - -From the computational point of view, the structure of the proof of -:g:`(or A B)` in this term is needed for computing the boolean value. - -In general, if :math:`I` has type :math:`\Prop` then :math:`P` cannot have type :math:`I→\Set`, because -it will mean to build an informative proof of type :math:`(P~m)` doing a case -analysis over a non-computational object that will disappear in the -extracted program. But the other way is safe with respect to our -interpretation we can have :math:`I` a computational object and :math:`P` a -non-computational one, it just corresponds to proving a logical property -of a computational object. - -In the same spirit, elimination on :math:`P` of type :math:`I→\Type` cannot be allowed -because it trivially implies the elimination on :math:`P` of type :math:`I→ \Set` by -cumulativity. It also implies that there are two proofs of the same -property which are provably different, contradicting the -proof-irrelevance property which is sometimes a useful axiom: - -.. example:: - - .. coqtop:: all - - Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y. - -The elimination of an inductive type of sort :math:`\Prop` on a predicate -:math:`P` of type :math:`I→ \Type` leads to a paradox when applied to impredicative -inductive definition like the second-order existential quantifier -:g:`exProp` defined above, because it gives access to the two projections on -this type. - - -.. _Empty-and-singleton-elimination: - -**Empty and singleton elimination.** There are special inductive definitions in -:math:`\Prop` for which more eliminations are allowed. - -.. inference:: Prop-extended - - I~\kw{is an empty or singleton definition} - s ∈ \Sort - ------------------------------------- - [I:\Prop|I→ s] - -A *singleton definition* has only one constructor and all the -arguments of this constructor have type :math:`\Prop`. In that case, there is a -canonical way to interpret the informative extraction on an object in -that type, such that the elimination on any sort :math:`s` is legal. Typical -examples are the conjunction of non-informative propositions and the -equality. If there is a hypothesis :math:`h:a=b` in the local context, it can -be used for rewriting not only in logical propositions but also in any -type. - -.. example:: - - .. coqtop:: all - - Print eq_rec. - Require Extraction. - Extraction eq_rec. - -An empty definition has no constructors, in that case also, -elimination on any sort is allowed. - -.. _Eliminaton-for-SProp: - -Inductive types in :math:`\SProp` must have no constructors (i.e. be -empty) to be eliminated to produce relevant values. - -Note that thanks to proof irrelevance elimination functions can be -produced for other types, for instance the elimination for a unit type -is the identity. - -.. _Type-of-branches: - -**Type of branches.** -Let :math:`c` be a term of type :math:`C`, we assume :math:`C` is a type of constructor for an -inductive type :math:`I`. Let :math:`P` be a term that represents the property to be -proved. We assume :math:`r` is the number of parameters and :math:`s` is the number of -arguments. - -We define a new type :math:`\{c:C\}^P` which represents the type of the branch -corresponding to the :math:`c:C` constructor. - -.. math:: - \begin{array}{ll} - \{c:(I~q_1\ldots q_r\ t_1 \ldots t_s)\}^P &\equiv (P~t_1\ldots ~t_s~c) \\ - \{c:∀ x:T,~C\}^P &\equiv ∀ x:T,~\{(c~x):C\}^P - \end{array} - -We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:`c`. - - -.. example:: - - The following term in concrete syntax:: - - match t as l return P' with - | nil _ => t1 - | cons _ hd tl => t2 - end - - - can be represented in abstract syntax as - - .. math:: - \case(t,P,f_1 | f_2 ) - - where - - .. math:: - :nowrap: - - \begin{eqnarray*} - P & = & λ l.~P^\prime\\ - f_1 & = & t_1\\ - f_2 & = & λ (hd:\nat).~λ (tl:\List~\nat).~t_2 - \end{eqnarray*} - - According to the definition: - - .. math:: - \{(\Nil~\nat)\}^P ≡ \{(\Nil~\nat) : (\List~\nat)\}^P ≡ (P~(\Nil~\nat)) - - .. math:: - - \begin{array}{rl} - \{(\cons~\nat)\}^P & ≡\{(\cons~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\ - & ≡∀ n:\nat,~\{(\cons~\nat~n) : (\List~\nat→\List~\nat)\}^P \\ - & ≡∀ n:\nat,~∀ l:\List~\nat,~\{(\cons~\nat~n~l) : (\List~\nat)\}^P \\ - & ≡∀ n:\nat,~∀ l:\List~\nat,~(P~(\cons~\nat~n~l)). - \end{array} - - Given some :math:`P` then :math:`\{(\Nil~\nat)\}^P` represents the expected type of :math:`f_1`, - and :math:`\{(\cons~\nat)\}^P` represents the expected type of :math:`f_2`. - - -.. _Typing-rule: - -**Typing rule.** -Our very general destructor for inductive definition enjoys the -following typing rule - -.. inference:: match - - \begin{array}{l} - E[Γ] ⊢ c : (I~q_1 … q_r~t_1 … t_s ) \\ - E[Γ] ⊢ P : B \\ - [(I~q_1 … q_r)|B] \\ - (E[Γ] ⊢ f_i : \{(c_{p_i}~q_1 … q_r)\}^P)_{i=1… l} - \end{array} - ------------------------------------------------ - E[Γ] ⊢ \case(c,P,f_1 |… |f_l ) : (P~t_1 … t_s~c) - -provided :math:`I` is an inductive type in a -definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;~…;~c_n :C_n ]` and -:math:`c_{p_1} … c_{p_l}` are the only constructors of :math:`I`. - - - -.. example:: - - Below is a typing rule for the term shown in the previous example: - - .. inference:: list example - - \begin{array}{l} - E[Γ] ⊢ t : (\List ~\nat) \\ - E[Γ] ⊢ P : B \\ - [(\List ~\nat)|B] \\ - E[Γ] ⊢ f_1 : \{(\Nil ~\nat)\}^P \\ - E[Γ] ⊢ f_2 : \{(\cons ~\nat)\}^P - \end{array} - ------------------------------------------------ - E[Γ] ⊢ \case(t,P,f_1 |f_2 ) : (P~t) - - -.. _Definition-of-ι-reduction: - -**Definition of ι-reduction.** -We still have to define the ι-reduction in the general case. - -An ι-redex is a term of the following form: - -.. math:: - \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) - -with :math:`c_{p_i}` the :math:`i`-th constructor of the inductive type :math:`I` with :math:`r` -parameters. - -The ι-contraction of this term is :math:`(f_i~a_1 … a_m )` leading to the -general reduction rule: - -.. math:: - \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) \triangleright_ι (f_i~a_1 … a_m ) - - -.. _Fixpoint-definitions: - -Fixpoint definitions -~~~~~~~~~~~~~~~~~~~~ - -The second operator for elimination is fixpoint definition. This -fixpoint may involve several mutually recursive definitions. The basic -concrete syntax for a recursive set of mutually recursive declarations -is (with :math:`Γ_i` contexts): - -.. math:: - \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n - - -The terms are obtained by projections from this set of declarations -and are written - -.. math:: - \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n~\for~f_i - -In the inference rules, we represent such a term by - -.. math:: - \Fix~f_i\{f_1 :A_1':=t_1' … f_n :A_n':=t_n'\} - -with :math:`t_i'` (resp. :math:`A_i'`) representing the term :math:`t_i` abstracted (resp. -generalized) with respect to the bindings in the context :math:`Γ_i`, namely -:math:`t_i'=λ Γ_i . t_i` and :math:`A_i'=∀ Γ_i , A_i`. - - -Typing rule -+++++++++++ - -The typing rule is the expected one for a fixpoint. - -.. inference:: Fix - - (E[Γ] ⊢ A_i : s_i )_{i=1… n} - (E[Γ;~f_1 :A_1 ;~…;~f_n :A_n ] ⊢ t_i : A_i )_{i=1… n} - ------------------------------------------------------- - E[Γ] ⊢ \Fix~f_i\{f_1 :A_1 :=t_1 … f_n :A_n :=t_n \} : A_i - - -Any fixpoint definition cannot be accepted because non-normalizing -terms allow proofs of absurdity. The basic scheme of recursion that -should be allowed is the one needed for defining primitive recursive -functionals. In that case the fixpoint enjoys a special syntactic -restriction, namely one of the arguments belongs to an inductive type, -the function starts with a case analysis and recursive calls are done -on variables coming from patterns and representing subterms. For -instance in the case of natural numbers, a proof of the induction -principle of type - -.. math:: - ∀ P:\nat→\Prop,~(P~\nO)→(∀ n:\nat,~(P~n)→(P~(\nS~n)))→ ∀ n:\nat,~(P~n) - -can be represented by the term: - -.. math:: - \begin{array}{l} - λ P:\nat→\Prop.~λ f:(P~\nO).~λ g:(∀ n:\nat,~(P~n)→(P~(\nS~n))).\\ - \Fix~h\{h:∀ n:\nat,~(P~n):=λ n:\nat.~\case(n,P,f | λp:\nat.~(g~p~(h~p)))\} - \end{array} - -Before accepting a fixpoint definition as being correctly typed, we -check that the definition is “guarded”. A precise analysis of this -notion can be found in :cite:`Gim94`. The first stage is to precise on which -argument the fixpoint will be decreasing. The type of this argument -should be an inductive type. For doing this, the syntax of -fixpoints is extended and becomes - -.. math:: - \Fix~f_i\{f_1/k_1 :A_1:=t_1 … f_n/k_n :A_n:=t_n\} - - -where :math:`k_i` are positive integers. Each :math:`k_i` represents the index of -parameter of :math:`f_i`, on which :math:`f_i` is decreasing. Each :math:`A_i` should be a -type (reducible to a term) starting with at least :math:`k_i` products -:math:`∀ y_1 :B_1 ,~… ∀ y_{k_i} :B_{k_i} ,~A_i'` and :math:`B_{k_i}` an inductive type. - -Now in the definition :math:`t_i`, if :math:`f_j` occurs then it should be applied to -at least :math:`k_j` arguments and the :math:`k_j`-th argument should be -syntactically recognized as structurally smaller than :math:`y_{k_i}`. - -The definition of being structurally smaller is a bit technical. One -needs first to define the notion of *recursive arguments of a -constructor*. For an inductive definition :math:`\ind{r}{Γ_I}{Γ_C}`, if the -type of a constructor :math:`c` has the form -:math:`∀ p_1 :P_1 ,~… ∀ p_r :P_r,~∀ x_1:T_1,~… ∀ x_m :T_m,~(I_j~p_1 … p_r~t_1 … t_s )`, -then the recursive -arguments will correspond to :math:`T_i` in which one of the :math:`I_l` occurs. - -The main rules for being structurally smaller are the following. -Given a variable :math:`y` of an inductively defined type in a declaration -:math:`\ind{r}{Γ_I}{Γ_C}` where :math:`Γ_I` is :math:`[I_1 :A_1 ;~…;~I_k :A_k]`, and :math:`Γ_C` is -:math:`[c_1 :C_1 ;~…;~c_n :C_n ]`, the terms structurally smaller than :math:`y` are: - - -+ :math:`(t~u)` and :math:`λ x:U .~t` when :math:`t` is structurally smaller than :math:`y`. -+ :math:`\case(c,P,f_1 … f_n)` when each :math:`f_i` is structurally smaller than :math:`y`. - If :math:`c` is :math:`y` or is structurally smaller than :math:`y`, its type is an inductive - type :math:`I_p` part of the inductive definition corresponding to :math:`y`. - Each :math:`f_i` corresponds to a type of constructor - :math:`C_q ≡ ∀ p_1 :P_1 ,~…,∀ p_r :P_r ,~∀ y_1 :B_1 ,~… ∀ y_m :B_m ,~(I_p~p_1 … p_r~t_1 … t_s )` - and can consequently be written :math:`λ y_1 :B_1' .~… λ y_m :B_m'.~g_i`. (:math:`B_i'` is - obtained from :math:`B_i` by substituting parameters for variables) the variables - :math:`y_j` occurring in :math:`g_i` corresponding to recursive arguments :math:`B_i` (the - ones in which one of the :math:`I_l` occurs) are structurally smaller than :math:`y`. - - -The following definitions are correct, we enter them using the :cmd:`Fixpoint` -command and show the internal representation. - -.. example:: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (plus p m) - end. - - Print plus. - Fixpoint lgth (A:Set) (l:list A) {struct l} : nat := - match l with - | nil _ => O - | cons _ a l' => S (lgth A l') - end. - Print lgth. - Fixpoint sizet (t:tree) : nat := let (f) := t in S (sizef f) - with sizef (f:forest) : nat := - match f with - | emptyf => O - | consf t f => plus (sizet t) (sizef f) - end. - Print sizet. - -.. _Reduction-rule: - -Reduction rule -++++++++++++++ - -Let :math:`F` be the set of declarations: -:math:`f_1 /k_1 :A_1 :=t_1 …f_n /k_n :A_n:=t_n`. -The reduction for fixpoints is: - -.. math:: - (\Fix~f_i \{F\}~a_1 …a_{k_i}) ~\triangleright_ι~ \subst{t_i}{f_k}{\Fix~f_k \{F\}}_{k=1… n} ~a_1 … a_{k_i} - -when :math:`a_{k_i}` starts with a constructor. This last restriction is needed -in order to keep strong normalization and corresponds to the reduction -for primitive recursive operators. The following reductions are now -possible: - -.. math:: - :nowrap: - - \begin{eqnarray*} - \plus~(\nS~(\nS~\nO))~(\nS~\nO)~& \trii & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\ - & \trii & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\ - & \trii & \nS~(\nS~(\nS~\nO))\\ - \end{eqnarray*} - -.. _Mutual-induction: - -**Mutual induction** - -The principles of mutual induction can be automatically generated -using the Scheme command described in Section :ref:`proofschemes-induction-principles`. - - -.. _Admissible-rules-for-global-environments: - -Admissible rules for global environments --------------------------------------------- - -From the original rules of the type system, one can show the -admissibility of rules which change the local context of definition of -objects in the global environment. We show here the admissible rules -that are used in the discharge mechanism at the end of a section. - - -.. _Abstraction: - -**Abstraction.** -One can modify a global declaration by generalizing it over a -previously assumed constant :math:`c`. For doing that, we need to modify the -reference to the global declaration in the subsequent global -environment and local context by explicitly applying this constant to -the constant :math:`c`. - -Below, if :math:`Γ` is a context of the form :math:`[y_1 :A_1 ;~…;~y_n :A_n]`, we write -:math:`∀x:U,~\subst{Γ}{c}{x}` to mean -:math:`[y_1 :∀ x:U,~\subst{A_1}{c}{x};~…;~y_n :∀ x:U,~\subst{A_n}{c}{x}]` -and :math:`\subst{E}{|Γ|}{|Γ|c}` to mean the parallel substitution -:math:`E\{y_1 /(y_1~c)\}…\{y_n/(y_n~c)\}`. - - -.. _First-abstracting-property: - -**First abstracting property:** - -.. math:: - \frac{\WF{E;~c:U;~E′;~c′:=t:T;~E″}{Γ}} - {\WF{E;~c:U;~E′;~c′:=λ x:U.~\subst{t}{c}{x}:∀x:U,~\subst{T}{c}{x};~\subst{E″}{c′}{(c′~c)}} - {\subst{Γ}{c′}{(c′~c)}}} - - -.. math:: - \frac{\WF{E;~c:U;~E′;~c′:T;~E″}{Γ}} - {\WF{E;~c:U;~E′;~c′:∀ x:U,~\subst{T}{c}{x};~\subst{E″}{c′}{(c′~c)}}{\subst{Γ}{c′}{(c′~c)}}} - -.. math:: - \frac{\WF{E;~c:U;~E′;~\ind{p}{Γ_I}{Γ_C};~E″}{Γ}} - {\WFTWOLINES{E;~c:U;~E′;~\ind{p+1}{∀ x:U,~\subst{Γ_I}{c}{x}}{∀ x:U,~\subst{Γ_C}{c}{x}};~ - \subst{E″}{|Γ_I ;Γ_C |}{|Γ_I ;Γ_C | c}} - {\subst{Γ}{|Γ_I ;Γ_C|}{|Γ_I ;Γ_C | c}}} - -One can similarly modify a global declaration by generalizing it over -a previously defined constant :math:`c`. Below, if :math:`Γ` is a context of the form -:math:`[y_1 :A_1 ;~…;~y_n :A_n]`, we write :math:`\subst{Γ}{c}{u}` to mean -:math:`[y_1 :\subst{A_1} {c}{u};~…;~y_n:\subst{A_n} {c}{u}]`. - - -.. _Second-abstracting-property: - -**Second abstracting property:** - -.. math:: - \frac{\WF{E;~c:=u:U;~E′;~c′:=t:T;~E″}{Γ}} - {\WF{E;~c:=u:U;~E′;~c′:=(\letin{x}{u:U}{\subst{t}{c}{x}}):\subst{T}{c}{u};~E″}{Γ}} - -.. math:: - \frac{\WF{E;~c:=u:U;~E′;~c′:T;~E″}{Γ}} - {\WF{E;~c:=u:U;~E′;~c′:\subst{T}{c}{u};~E″}{Γ}} - -.. math:: - \frac{\WF{E;~c:=u:U;~E′;~\ind{p}{Γ_I}{Γ_C};~E″}{Γ}} - {\WF{E;~c:=u:U;~E′;~\ind{p}{\subst{Γ_I}{c}{u}}{\subst{Γ_C}{c}{u}};~E″}{Γ}} - -.. _Pruning-the-local-context: - -**Pruning the local context.** -If one abstracts or substitutes constants with the above rules then it -may happen that some declared or defined constant does not occur any -more in the subsequent global environment and in the local context. -One can consequently derive the following property. - - -.. _First-pruning-property: - -.. inference:: First pruning property: - - \WF{E;~c:U;~E′}{Γ} - c~\kw{does not occur in}~E′~\kw{and}~Γ - -------------------------------------- - \WF{E;E′}{Γ} - - -.. _Second-pruning-property: - -.. inference:: Second pruning property: - - \WF{E;~c:=u:U;~E′}{Γ} - c~\kw{does not occur in}~E′~\kw{and}~Γ - -------------------------------------- - \WF{E;E′}{Γ} - - -.. _Co-inductive-types: - -Co-inductive types ----------------------- - -The implementation contains also co-inductive definitions, which are -types inhabited by infinite objects. More information on co-inductive -definitions can be found in :cite:`Gimenez95b,Gim98,GimCas05`. - - -.. _The-Calculus-of-Inductive-Construction-with-impredicative-Set: - -The Calculus of Inductive Constructions with impredicative Set ------------------------------------------------------------------ - -|Coq| can be used as a type checker for the Calculus of Inductive -Constructions with an impredicative sort :math:`\Set` by using the compiler -option ``-impredicative-set``. For example, using the ordinary `coqtop` -command, the following is rejected, - -.. example:: - - .. coqtop:: all - - Fail Definition id: Set := forall X:Set,X->X. - -while it will type check, if one uses instead the `coqtop` -``-impredicative-set`` option.. - -The major change in the theory concerns the rule for product formation -in the sort :math:`\Set`, which is extended to a domain in any sort: - -.. inference:: ProdImp - - E[Γ] ⊢ T : s - s ∈ \Sort - E[Γ::(x:T)] ⊢ U : \Set - --------------------- - E[Γ] ⊢ ∀ x:T,~U : \Set - -This extension has consequences on the inductive definitions which are -allowed. In the impredicative system, one can build so-called *large -inductive definitions* like the example of second-order existential -quantifier (:g:`exSet`). - -There should be restrictions on the eliminations which can be -performed on such definitions. The elimination rules in the -impredicative system for sort :math:`\Set` become: - - - -.. inference:: Set1 - - s ∈ \{\Prop, \Set\} - ----------------- - [I:\Set|I→ s] - -.. inference:: Set2 - - I~\kw{is a small inductive definition} - s ∈ \{\Type(i)\} - ---------------- - [I:\Set|I→ s] -- cgit v1.2.3 From d5be454490a7dfb20b7cfffe6c547a2d9ec5f5f1 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 23:36:19 +0200 Subject: Create a new file on conversion. --- doc/sphinx/language/cic.rst | 212 -------------------------------- doc/sphinx/language/core/conversion.rst | 212 ++++++++++++++++++++++++++++++++ 2 files changed, 212 insertions(+), 212 deletions(-) delete mode 100644 doc/sphinx/language/cic.rst create mode 100644 doc/sphinx/language/core/conversion.rst diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst deleted file mode 100644 index 0f27b65107..0000000000 --- a/doc/sphinx/language/cic.rst +++ /dev/null @@ -1,212 +0,0 @@ -.. _Conversion-rules: - -Conversion rules --------------------- - -In |Cic|, there is an internal reduction mechanism. In particular, it -can decide if two programs are *intentionally* equal (one says -*convertible*). Convertibility is described in this section. - - -.. _beta-reduction: - -β-reduction -~~~~~~~~~~~ - -We want to be able to identify some terms as we can identify the -application of a function to a given argument with its result. For -instance the identity function over a given type :math:`T` can be written -:math:`λx:T.~x`. In any global environment :math:`E` and local context -:math:`Γ`, we want to identify any object :math:`a` (of type -:math:`T`) with the application :math:`((λ x:T.~x)~a)`. We define for -this a *reduction* (or a *conversion*) rule we call :math:`β`: - -.. math:: - - E[Γ] ⊢ ((λx:T.~t)~u)~\triangleright_β~\subst{t}{x}{u} - -We say that :math:`\subst{t}{x}{u}` is the *β-contraction* of -:math:`((λx:T.~t)~u)` and, conversely, that :math:`((λ x:T.~t)~u)` is the -*β-expansion* of :math:`\subst{t}{x}{u}`. - -According to β-reduction, terms of the *Calculus of Inductive -Constructions* enjoy some fundamental properties such as confluence, -strong normalization, subject reduction. These results are -theoretically of great importance but we will not detail them here and -refer the interested reader to :cite:`Coq85`. - - -.. _iota-reduction: - -ι-reduction -~~~~~~~~~~~ - -A specific conversion rule is associated to the inductive objects in -the global environment. We shall give later on (see Section -:ref:`Well-formed-inductive-definitions`) the precise rules but it -just says that a destructor applied to an object built from a -constructor behaves as expected. This reduction is called ι-reduction -and is more precisely studied in :cite:`Moh93,Wer94`. - - -.. _delta-reduction: - -δ-reduction -~~~~~~~~~~~ - -We may have variables defined in local contexts or constants defined -in the global environment. It is legal to identify such a reference -with its value, that is to expand (or unfold) it into its value. This -reduction is called δ-reduction and shows as follows. - -.. inference:: Delta-Local - - \WFE{\Gamma} - (x:=t:T) ∈ Γ - -------------- - E[Γ] ⊢ x~\triangleright_Δ~t - -.. inference:: Delta-Global - - \WFE{\Gamma} - (c:=t:T) ∈ E - -------------- - E[Γ] ⊢ c~\triangleright_δ~t - - -.. _zeta-reduction: - -ζ-reduction -~~~~~~~~~~~ - -|Coq| allows also to remove local definitions occurring in terms by -replacing the defined variable by its value. The declaration being -destroyed, this reduction differs from δ-reduction. It is called -ζ-reduction and shows as follows. - -.. inference:: Zeta - - \WFE{\Gamma} - \WTEG{u}{U} - \WTE{\Gamma::(x:=u:U)}{t}{T} - -------------- - E[Γ] ⊢ \letin{x}{u:U}{t}~\triangleright_ζ~\subst{t}{x}{u} - - -.. _eta-expansion: - -η-expansion -~~~~~~~~~~~ - -Another important concept is η-expansion. It is legal to identify any -term :math:`t` of functional type :math:`∀ x:T,~U` with its so-called η-expansion - -.. math:: - λx:T.~(t~x) - -for :math:`x` an arbitrary variable name fresh in :math:`t`. - - -.. note:: - - We deliberately do not define η-reduction: - - .. math:: - λ x:T.~(t~x)~\not\triangleright_η~t - - This is because, in general, the type of :math:`t` need not to be convertible - to the type of :math:`λ x:T.~(t~x)`. E.g., if we take :math:`f` such that: - - .. math:: - f ~:~ ∀ x:\Type(2),~\Type(1) - - then - - .. math:: - λ x:\Type(1).~(f~x) ~:~ ∀ x:\Type(1),~\Type(1) - - We could not allow - - .. math:: - λ x:\Type(1).~(f~x) ~\triangleright_η~ f - - because the type of the reduced term :math:`∀ x:\Type(2),~\Type(1)` would not be - convertible to the type of the original term :math:`∀ x:\Type(1),~\Type(1)`. - -.. _proof-irrelevance: - -Proof Irrelevance -~~~~~~~~~~~~~~~~~ - -It is legal to identify any two terms whose common type is a strict -proposition :math:`A : \SProp`. Terms in a strict propositions are -therefore called *irrelevant*. - -.. _convertibility: - -Convertibility -~~~~~~~~~~~~~~ - -Let us write :math:`E[Γ] ⊢ t \triangleright u` for the contextual closure of the -relation :math:`t` reduces to :math:`u` in the global environment -:math:`E` and local context :math:`Γ` with one of the previous -reductions β, δ, ι or ζ. - -We say that two terms :math:`t_1` and :math:`t_2` are -*βδιζη-convertible*, or simply *convertible*, or *equivalent*, in the -global environment :math:`E` and local context :math:`Γ` iff there -exist terms :math:`u_1` and :math:`u_2` such that :math:`E[Γ] ⊢ t_1 \triangleright -… \triangleright u_1` and :math:`E[Γ] ⊢ t_2 \triangleright … \triangleright u_2` and either :math:`u_1` and -:math:`u_2` are identical up to irrelevant subterms, or they are convertible up to η-expansion, -i.e. :math:`u_1` is :math:`λ x:T.~u_1'` and :math:`u_2 x` is -recursively convertible to :math:`u_1'`, or, symmetrically, -:math:`u_2` is :math:`λx:T.~u_2'` -and :math:`u_1 x` is recursively convertible to :math:`u_2'`. We then write -:math:`E[Γ] ⊢ t_1 =_{βδιζη} t_2`. - -Apart from this we consider two instances of polymorphic and -cumulative (see Chapter :ref:`polymorphicuniverses`) inductive types -(see below) convertible - -.. math:: - E[Γ] ⊢ t~w_1 … w_m =_{βδιζη} t~w_1' … w_m' - -if we have subtypings (see below) in both directions, i.e., - -.. math:: - E[Γ] ⊢ t~w_1 … w_m ≤_{βδιζη} t~w_1' … w_m' - -and - -.. math:: - E[Γ] ⊢ t~w_1' … w_m' ≤_{βδιζη} t~w_1 … w_m. - -Furthermore, we consider - -.. math:: - E[Γ] ⊢ c~v_1 … v_m =_{βδιζη} c'~v_1' … v_m' - -convertible if - -.. math:: - E[Γ] ⊢ v_i =_{βδιζη} v_i' - -and we have that :math:`c` and :math:`c'` -are the same constructors of different instances of the same inductive -types (differing only in universe levels) such that - -.. math:: - E[Γ] ⊢ c~v_1 … v_m : t~w_1 … w_m - -and - -.. math:: - E[Γ] ⊢ c'~v_1' … v_m' : t'~ w_1' … w_m ' - -and we have - -.. math:: - E[Γ] ⊢ t~w_1 … w_m =_{βδιζη} t~w_1' … w_m'. - -The convertibility relation allows introducing a new typing rule which -says that two convertible well-formed types have the same inhabitants. diff --git a/doc/sphinx/language/core/conversion.rst b/doc/sphinx/language/core/conversion.rst new file mode 100644 index 0000000000..0f27b65107 --- /dev/null +++ b/doc/sphinx/language/core/conversion.rst @@ -0,0 +1,212 @@ +.. _Conversion-rules: + +Conversion rules +-------------------- + +In |Cic|, there is an internal reduction mechanism. In particular, it +can decide if two programs are *intentionally* equal (one says +*convertible*). Convertibility is described in this section. + + +.. _beta-reduction: + +β-reduction +~~~~~~~~~~~ + +We want to be able to identify some terms as we can identify the +application of a function to a given argument with its result. For +instance the identity function over a given type :math:`T` can be written +:math:`λx:T.~x`. In any global environment :math:`E` and local context +:math:`Γ`, we want to identify any object :math:`a` (of type +:math:`T`) with the application :math:`((λ x:T.~x)~a)`. We define for +this a *reduction* (or a *conversion*) rule we call :math:`β`: + +.. math:: + + E[Γ] ⊢ ((λx:T.~t)~u)~\triangleright_β~\subst{t}{x}{u} + +We say that :math:`\subst{t}{x}{u}` is the *β-contraction* of +:math:`((λx:T.~t)~u)` and, conversely, that :math:`((λ x:T.~t)~u)` is the +*β-expansion* of :math:`\subst{t}{x}{u}`. + +According to β-reduction, terms of the *Calculus of Inductive +Constructions* enjoy some fundamental properties such as confluence, +strong normalization, subject reduction. These results are +theoretically of great importance but we will not detail them here and +refer the interested reader to :cite:`Coq85`. + + +.. _iota-reduction: + +ι-reduction +~~~~~~~~~~~ + +A specific conversion rule is associated to the inductive objects in +the global environment. We shall give later on (see Section +:ref:`Well-formed-inductive-definitions`) the precise rules but it +just says that a destructor applied to an object built from a +constructor behaves as expected. This reduction is called ι-reduction +and is more precisely studied in :cite:`Moh93,Wer94`. + + +.. _delta-reduction: + +δ-reduction +~~~~~~~~~~~ + +We may have variables defined in local contexts or constants defined +in the global environment. It is legal to identify such a reference +with its value, that is to expand (or unfold) it into its value. This +reduction is called δ-reduction and shows as follows. + +.. inference:: Delta-Local + + \WFE{\Gamma} + (x:=t:T) ∈ Γ + -------------- + E[Γ] ⊢ x~\triangleright_Δ~t + +.. inference:: Delta-Global + + \WFE{\Gamma} + (c:=t:T) ∈ E + -------------- + E[Γ] ⊢ c~\triangleright_δ~t + + +.. _zeta-reduction: + +ζ-reduction +~~~~~~~~~~~ + +|Coq| allows also to remove local definitions occurring in terms by +replacing the defined variable by its value. The declaration being +destroyed, this reduction differs from δ-reduction. It is called +ζ-reduction and shows as follows. + +.. inference:: Zeta + + \WFE{\Gamma} + \WTEG{u}{U} + \WTE{\Gamma::(x:=u:U)}{t}{T} + -------------- + E[Γ] ⊢ \letin{x}{u:U}{t}~\triangleright_ζ~\subst{t}{x}{u} + + +.. _eta-expansion: + +η-expansion +~~~~~~~~~~~ + +Another important concept is η-expansion. It is legal to identify any +term :math:`t` of functional type :math:`∀ x:T,~U` with its so-called η-expansion + +.. math:: + λx:T.~(t~x) + +for :math:`x` an arbitrary variable name fresh in :math:`t`. + + +.. note:: + + We deliberately do not define η-reduction: + + .. math:: + λ x:T.~(t~x)~\not\triangleright_η~t + + This is because, in general, the type of :math:`t` need not to be convertible + to the type of :math:`λ x:T.~(t~x)`. E.g., if we take :math:`f` such that: + + .. math:: + f ~:~ ∀ x:\Type(2),~\Type(1) + + then + + .. math:: + λ x:\Type(1).~(f~x) ~:~ ∀ x:\Type(1),~\Type(1) + + We could not allow + + .. math:: + λ x:\Type(1).~(f~x) ~\triangleright_η~ f + + because the type of the reduced term :math:`∀ x:\Type(2),~\Type(1)` would not be + convertible to the type of the original term :math:`∀ x:\Type(1),~\Type(1)`. + +.. _proof-irrelevance: + +Proof Irrelevance +~~~~~~~~~~~~~~~~~ + +It is legal to identify any two terms whose common type is a strict +proposition :math:`A : \SProp`. Terms in a strict propositions are +therefore called *irrelevant*. + +.. _convertibility: + +Convertibility +~~~~~~~~~~~~~~ + +Let us write :math:`E[Γ] ⊢ t \triangleright u` for the contextual closure of the +relation :math:`t` reduces to :math:`u` in the global environment +:math:`E` and local context :math:`Γ` with one of the previous +reductions β, δ, ι or ζ. + +We say that two terms :math:`t_1` and :math:`t_2` are +*βδιζη-convertible*, or simply *convertible*, or *equivalent*, in the +global environment :math:`E` and local context :math:`Γ` iff there +exist terms :math:`u_1` and :math:`u_2` such that :math:`E[Γ] ⊢ t_1 \triangleright +… \triangleright u_1` and :math:`E[Γ] ⊢ t_2 \triangleright … \triangleright u_2` and either :math:`u_1` and +:math:`u_2` are identical up to irrelevant subterms, or they are convertible up to η-expansion, +i.e. :math:`u_1` is :math:`λ x:T.~u_1'` and :math:`u_2 x` is +recursively convertible to :math:`u_1'`, or, symmetrically, +:math:`u_2` is :math:`λx:T.~u_2'` +and :math:`u_1 x` is recursively convertible to :math:`u_2'`. We then write +:math:`E[Γ] ⊢ t_1 =_{βδιζη} t_2`. + +Apart from this we consider two instances of polymorphic and +cumulative (see Chapter :ref:`polymorphicuniverses`) inductive types +(see below) convertible + +.. math:: + E[Γ] ⊢ t~w_1 … w_m =_{βδιζη} t~w_1' … w_m' + +if we have subtypings (see below) in both directions, i.e., + +.. math:: + E[Γ] ⊢ t~w_1 … w_m ≤_{βδιζη} t~w_1' … w_m' + +and + +.. math:: + E[Γ] ⊢ t~w_1' … w_m' ≤_{βδιζη} t~w_1 … w_m. + +Furthermore, we consider + +.. math:: + E[Γ] ⊢ c~v_1 … v_m =_{βδιζη} c'~v_1' … v_m' + +convertible if + +.. math:: + E[Γ] ⊢ v_i =_{βδιζη} v_i' + +and we have that :math:`c` and :math:`c'` +are the same constructors of different instances of the same inductive +types (differing only in universe levels) such that + +.. math:: + E[Γ] ⊢ c~v_1 … v_m : t~w_1 … w_m + +and + +.. math:: + E[Γ] ⊢ c'~v_1' … v_m' : t'~ w_1' … w_m ' + +and we have + +.. math:: + E[Γ] ⊢ t~w_1 … w_m =_{βδιζη} t~w_1' … w_m'. + +The convertibility relation allows introducing a new typing rule which +says that two convertible well-formed types have the same inhabitants. -- cgit v1.2.3 From 039d0f96bd9c49d0c8bec5d4431e1603f75f2ac6 Mon Sep 17 00:00:00 2001 From: Théo Zimmermann Date: Wed, 13 May 2020 23:53:55 +0200 Subject: Preserve sections about typing rules in CIC chapter. --- doc/sphinx/language/cic.rst | 1522 +------------------------------------------ 1 file changed, 1 insertion(+), 1521 deletions(-) diff --git a/doc/sphinx/language/cic.rst b/doc/sphinx/language/cic.rst index b125d21a3c..5f74958712 100644 --- a/doc/sphinx/language/cic.rst +++ b/doc/sphinx/language/cic.rst @@ -1,7 +1,4 @@ -.. _calculusofinductiveconstructions: - - -Calculus of Inductive Constructions +Typing rules ==================================== The underlying formal language of |Coq| is a *Calculus of Inductive @@ -24,95 +21,6 @@ to a type and takes the form “*for all x of type* :math:`T`, :math:`P`”. The “:math:`x` *of type* :math:`T`” is written “:math:`x:T`”. Informally, “:math:`x:T`” can be thought as “:math:`x` *belongs to* :math:`T`”. -The types of types are called :gdef:`sort`\s. Types and sorts are themselves terms -so that terms, types and sorts are all components of a common -syntactic language of terms which is described in Section :ref:`terms`. But -first, we describe sorts. - - -.. _Sorts: - -Sorts -~~~~~~~~~~~ - -All sorts have a type and there is an infinite well-founded typing -hierarchy of sorts whose base sorts are :math:`\SProp`, :math:`\Prop` -and :math:`\Set`. - -The sort :math:`\Prop` intends to be the type of logical propositions. If :math:`M` is a -logical proposition then it denotes the class of terms representing -proofs of :math:`M`. An object :math:`m` belonging to :math:`M` witnesses the fact that :math:`M` is -provable. An object of type :math:`\Prop` is called a proposition. - -The sort :math:`\SProp` is like :math:`\Prop` but the propositions in -:math:`\SProp` are known to have irrelevant proofs (all proofs are -equal). Objects of type :math:`\SProp` are called strict propositions. -See :ref:`sprop` for information about using -:math:`\SProp`, and :cite:`Gilbert:POPL2019` for meta theoretical -considerations. - -The sort :math:`\Set` intends to be the type of small sets. This includes data -types such as booleans and naturals, but also products, subsets, and -function types over these data types. - -:math:`\SProp`, :math:`\Prop` and :math:`\Set` themselves can be manipulated as ordinary terms. -Consequently they also have a type. Because assuming simply that :math:`\Set` -has type :math:`\Set` leads to an inconsistent theory :cite:`Coq86`, the language of -|Cic| has infinitely many sorts. There are, in addition to the base sorts, -a hierarchy of universes :math:`\Type(i)` for any integer :math:`i ≥ 1`. - -Like :math:`\Set`, all of the sorts :math:`\Type(i)` contain small sets such as -booleans, natural numbers, as well as products, subsets and function -types over small sets. But, unlike :math:`\Set`, they also contain large sets, -namely the sorts :math:`\Set` and :math:`\Type(j)` for :math:`j list A -> list A. - -.. example:: - - The declaration for a mutual inductive definition of tree and forest - is: - - .. math:: - \ind{0}{\left[\begin{array}{rcl}\tree&:&\Set\\\forest&:&\Set\end{array}\right]} - {\left[\begin{array}{rcl} - \node &:& \forest → \tree\\ - \emptyf &:& \forest\\ - \consf &:& \tree → \forest → \forest\\ - \end{array}\right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive tree : Set := - | node : forest -> tree - with forest : Set := - | emptyf : forest - | consf : tree -> forest -> forest. - -.. example:: - - The declaration for a mutual inductive definition of even and odd is: - - .. math:: - \ind{0}{\left[\begin{array}{rcl}\even&:&\nat → \Prop \\ - \odd&:&\nat → \Prop \end{array}\right]} - {\left[\begin{array}{rcl} - \evenO &:& \even~0\\ - \evenS &:& ∀ n,~\odd~n → \even~(\nS~n)\\ - \oddS &:& ∀ n,~\even~n → \odd~(\nS~n) - \end{array}\right]} - - which corresponds to the result of the |Coq| declaration: - - .. coqtop:: in - - Inductive even : nat -> Prop := - | even_O : even 0 - | even_S : forall n, odd n -> even (S n) - with odd : nat -> Prop := - | odd_S : forall n, even n -> odd (S n). - - - -.. _Types-of-inductive-objects: - -Types of inductive objects -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We have to give the type of constants in a global environment :math:`E` which -contains an inductive definition. - -.. inference:: Ind - - \WFE{Γ} - \ind{p}{Γ_I}{Γ_C} ∈ E - (a:A)∈Γ_I - --------------------- - E[Γ] ⊢ a : A - -.. inference:: Constr - - \WFE{Γ} - \ind{p}{Γ_I}{Γ_C} ∈ E - (c:C)∈Γ_C - --------------------- - E[Γ] ⊢ c : C - -.. example:: - - Provided that our environment :math:`E` contains inductive definitions we showed before, - these two inference rules above enable us to conclude that: - - .. math:: - \begin{array}{l} - E[Γ] ⊢ \even : \nat→\Prop\\ - E[Γ] ⊢ \odd : \nat→\Prop\\ - E[Γ] ⊢ \evenO : \even~\nO\\ - E[Γ] ⊢ \evenS : ∀ n:\nat,~\odd~n → \even~(\nS~n)\\ - E[Γ] ⊢ \oddS : ∀ n:\nat,~\even~n → \odd~(\nS~n) - \end{array} - - - - -.. _Well-formed-inductive-definitions: - -Well-formed inductive definitions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We cannot accept any inductive definition because some of them lead -to inconsistent systems. We restrict ourselves to definitions which -satisfy a syntactic criterion of positivity. Before giving the formal -rules, we need a few definitions: - -Arity of a given sort -+++++++++++++++++++++ - -A type :math:`T` is an *arity of sort* :math:`s` if it converts to the sort :math:`s` or to a -product :math:`∀ x:T,~U` with :math:`U` an arity of sort :math:`s`. - -.. example:: - - :math:`A→\Set` is an arity of sort :math:`\Set`. :math:`∀ A:\Prop,~A→ \Prop` is an arity of sort - :math:`\Prop`. - - -Arity -+++++ -A type :math:`T` is an *arity* if there is a :math:`s∈ \Sort` such that :math:`T` is an arity of -sort :math:`s`. - - -.. example:: - - :math:`A→ \Set` and :math:`∀ A:\Prop,~A→ \Prop` are arities. - - -Type of constructor -+++++++++++++++++++ -We say that :math:`T` is a *type of constructor of* :math:`I` in one of the following -two cases: - -+ :math:`T` is :math:`(I~t_1 … t_n )` -+ :math:`T` is :math:`∀ x:U,~T'` where :math:`T'` is also a type of constructor of :math:`I` - -.. example:: - - :math:`\nat` and :math:`\nat→\nat` are types of constructor of :math:`\nat`. - :math:`∀ A:\Type,~\List~A` and :math:`∀ A:\Type,~A→\List~A→\List~A` are types of constructor of :math:`\List`. - -.. _positivity: - -Positivity Condition -++++++++++++++++++++ - -The type of constructor :math:`T` will be said to *satisfy the positivity -condition* for a constant :math:`X` in the following cases: - -+ :math:`T=(X~t_1 … t_n )` and :math:`X` does not occur free in any :math:`t_i` -+ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` - satisfies the positivity condition for :math:`X`. - -Strict positivity -+++++++++++++++++ - -The constant :math:`X` *occurs strictly positively* in :math:`T` in the following -cases: - - -+ :math:`X` does not occur in :math:`T` -+ :math:`T` converts to :math:`(X~t_1 … t_n )` and :math:`X` does not occur in any of :math:`t_i` -+ :math:`T` converts to :math:`∀ x:U,~V` and :math:`X` does not occur in type :math:`U` but occurs - strictly positively in type :math:`V` -+ :math:`T` converts to :math:`(I~a_1 … a_m~t_1 … t_p )` where :math:`I` is the name of an - inductive definition of the form - - .. math:: - \ind{m}{I:A}{c_1 :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_1 ;~…;~c_n :∀ p_1 :P_1 ,… ∀p_m :P_m ,~C_n} - - (in particular, it is - not mutually defined and it has :math:`m` parameters) and :math:`X` does not occur in - any of the :math:`t_i`, and the (instantiated) types of constructor - :math:`\subst{C_i}{p_j}{a_j}_{j=1… m}` of :math:`I` satisfy the nested positivity condition for :math:`X` - -Nested Positivity -+++++++++++++++++ - -The type of constructor :math:`T` of :math:`I` *satisfies the nested positivity -condition* for a constant :math:`X` in the following cases: - -+ :math:`T=(I~b_1 … b_m~u_1 … u_p)`, :math:`I` is an inductive type with :math:`m` - parameters and :math:`X` does not occur in any :math:`u_i` -+ :math:`T=∀ x:U,~V` and :math:`X` occurs only strictly positively in :math:`U` and the type :math:`V` - satisfies the nested positivity condition for :math:`X` - - -.. example:: - - For instance, if one considers the following variant of a tree type - branching over the natural numbers: - - .. coqtop:: in - - Inductive nattree (A:Type) : Type := - | leaf : nattree A - | natnode : A -> (nat -> nattree A) -> nattree A. - - Then every instantiated constructor of ``nattree A`` satisfies the nested positivity - condition for ``nattree``: - - + Type ``nattree A`` of constructor ``leaf`` satisfies the positivity condition for - ``nattree`` because ``nattree`` does not appear in any (real) arguments of the - type of that constructor (primarily because ``nattree`` does not have any (real) - arguments) ... (bullet 1) - - + Type ``A → (nat → nattree A) → nattree A`` of constructor ``natnode`` satisfies the - positivity condition for ``nattree`` because: - - - ``nattree`` occurs only strictly positively in ``A`` ... (bullet 1) - - - ``nattree`` occurs only strictly positively in ``nat → nattree A`` ... (bullet 3 + 2) - - - ``nattree`` satisfies the positivity condition for ``nattree A`` ... (bullet 1) - -.. _Correctness-rules: - -Correctness rules -+++++++++++++++++ - -We shall now describe the rules allowing the introduction of a new -inductive definition. - -Let :math:`E` be a global environment and :math:`Γ_P`, :math:`Γ_I`, :math:`Γ_C` be contexts -such that :math:`Γ_I` is :math:`[I_1 :∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k]`, and -:math:`Γ_C` is :math:`[c_1:∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n ]`. Then - -.. inference:: W-Ind - - \WFE{Γ_P} - (E[Γ_I ;Γ_P ] ⊢ C_i : s_{q_i} )_{i=1… n} - ------------------------------------------ - \WF{E;~\ind{p}{Γ_I}{Γ_C}}{} - - -provided that the following side conditions hold: - - + :math:`k>0` and all of :math:`I_j` and :math:`c_i` are distinct names for :math:`j=1… k` and :math:`i=1… n`, - + :math:`p` is the number of parameters of :math:`\ind{p}{Γ_I}{Γ_C}` and :math:`Γ_P` is the - context of parameters, - + for :math:`j=1… k` we have that :math:`A_j` is an arity of sort :math:`s_j` and :math:`I_j ∉ E`, - + for :math:`i=1… n` we have that :math:`C_i` is a type of constructor of :math:`I_{q_i}` which - satisfies the positivity condition for :math:`I_1 … I_k` and :math:`c_i ∉ E`. - -One can remark that there is a constraint between the sort of the -arity of the inductive type and the sort of the type of its -constructors which will always be satisfied for the impredicative -sorts :math:`\SProp` and :math:`\Prop` but may fail to define -inductive type on sort :math:`\Set` and generate constraints -between universes for inductive types in the Type hierarchy. - - -.. example:: - - It is well known that the existential quantifier can be encoded as an - inductive definition. The following declaration introduces the - second-order existential quantifier :math:`∃ X.P(X)`. - - .. coqtop:: in - - Inductive exProp (P:Prop->Prop) : Prop := - | exP_intro : forall X:Prop, P X -> exProp P. - - The same definition on :math:`\Set` is not allowed and fails: - - .. coqtop:: all - - Fail Inductive exSet (P:Set->Prop) : Set := - exS_intro : forall X:Set, P X -> exSet P. - - It is possible to declare the same inductive definition in the - universe :math:`\Type`. The :g:`exType` inductive definition has type - :math:`(\Type(i)→\Prop)→\Type(j)` with the constraint that the parameter :math:`X` of :math:`\kw{exT}_{\kw{intro}}` - has type :math:`\Type(k)` with :math:`kProp) : Type := - exT_intro : forall X:Type, P X -> exType P. - - -.. example:: Negative occurrence (first example) - - The following inductive definition is rejected because it does not - satisfy the positivity condition: - - .. coqtop:: all - - Fail Inductive I : Prop := not_I_I (not_I : I -> False) : I. - - If we were to accept such definition, we could derive a - contradiction from it (we can test this by disabling the - :flag:`Positivity Checking` flag): - - .. coqtop:: none - - Unset Positivity Checking. - Inductive I : Prop := not_I_I (not_I : I -> False) : I. - Set Positivity Checking. - - .. coqtop:: all - - Definition I_not_I : I -> ~ I := fun i => - match i with not_I_I not_I => not_I end. - - .. coqtop:: in - - Lemma contradiction : False. - Proof. - enough (I /\ ~ I) as [] by contradiction. - split. - - apply not_I_I. - intro. - now apply I_not_I. - - intro. - now apply I_not_I. - Qed. - -.. example:: Negative occurrence (second example) - - Here is another example of an inductive definition which is - rejected because it does not satify the positivity condition: - - .. coqtop:: all - - Fail Inductive Lam := lam (_ : Lam -> Lam). - - Again, if we were to accept it, we could derive a contradiction - (this time through a non-terminating recursive function): - - .. coqtop:: none - - Unset Positivity Checking. - Inductive Lam := lam (_ : Lam -> Lam). - Set Positivity Checking. - - .. coqtop:: all - - Fixpoint infinite_loop l : False := - match l with lam x => infinite_loop (x l) end. - - Check infinite_loop (lam (@id Lam)) : False. - -.. example:: Non strictly positive occurrence - - It is less obvious why inductive type definitions with occurences - that are positive but not strictly positive are harmful. - We will see that in presence of an impredicative type they - are unsound: - - .. coqtop:: all - - Fail Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. - - If we were to accept this definition we could derive a contradiction - by creating an injective function from :math:`A → \Prop` to :math:`A`. - - This function is defined by composing the injective constructor of - the type :math:`A` with the function :math:`λx. λz. z = x` injecting - any type :math:`T` into :math:`T → \Prop`. - - .. coqtop:: none - - Unset Positivity Checking. - Inductive A: Type := introA: ((A -> Prop) -> Prop) -> A. - Set Positivity Checking. - - .. coqtop:: all - - Definition f (x: A -> Prop): A := introA (fun z => z = x). - - .. coqtop:: in - - Lemma f_inj: forall x y, f x = f y -> x = y. - Proof. - unfold f; intros ? ? H; injection H. - set (F := fun z => z = y); intro HF. - symmetry; replace (y = x) with (F y). - + unfold F; reflexivity. - + rewrite <- HF; reflexivity. - Qed. - - The type :math:`A → \Prop` can be understood as the powerset - of the type :math:`A`. To derive a contradiction from the - injective function :math:`f` we use Cantor's classic diagonal - argument. - - .. coqtop:: all - - Definition d: A -> Prop := fun x => exists s, x = f s /\ ~s x. - Definition fd: A := f d. - - .. coqtop:: in - - Lemma cantor: (d fd) <-> ~(d fd). - Proof. - split. - + intros [s [H1 H2]]; unfold fd in H1. - replace d with s. - * assumption. - * apply f_inj; congruence. - + intro; exists d; tauto. - Qed. - - Lemma bad: False. - Proof. - pose cantor; tauto. - Qed. - - This derivation was first presented by Thierry Coquand and Christine - Paulin in :cite:`CP90`. - -.. _Template-polymorphism: - -Template polymorphism -+++++++++++++++++++++ - -Inductive types can be made polymorphic over the universes introduced by -their parameters in :math:`\Type`, if the minimal inferred sort of the -inductive declarations either mention some of those parameter universes -or is computed to be :math:`\Prop` or :math:`\Set`. - -If :math:`A` is an arity of some sort and :math:`s` is a sort, we write :math:`A_{/s}` -for the arity obtained from :math:`A` by replacing its sort with :math:`s`. -Especially, if :math:`A` is well-typed in some global environment and local -context, then :math:`A_{/s}` is typable by typability of all products in the -Calculus of Inductive Constructions. The following typing rule is -added to the theory. - -Let :math:`\ind{p}{Γ_I}{Γ_C}` be an inductive definition. Let -:math:`Γ_P = [p_1 :P_1 ;~…;~p_p :P_p ]` be its context of parameters, -:math:`Γ_I = [I_1:∀ Γ_P ,A_1 ;~…;~I_k :∀ Γ_P ,A_k ]` its context of definitions and -:math:`Γ_C = [c_1 :∀ Γ_P ,C_1 ;~…;~c_n :∀ Γ_P ,C_n]` its context of constructors, -with :math:`c_i` a constructor of :math:`I_{q_i}`. Let :math:`m ≤ p` be the length of the -longest prefix of parameters such that the :math:`m` first arguments of all -occurrences of all :math:`I_j` in all :math:`C_k` (even the occurrences in the -hypotheses of :math:`C_k`) are exactly applied to :math:`p_1 … p_m` (:math:`m` is the number -of *recursively uniform parameters* and the :math:`p−m` remaining parameters -are the *recursively non-uniform parameters*). Let :math:`q_1 , …, q_r`, with -:math:`0≤ r≤ m`, be a (possibly) partial instantiation of the recursively -uniform parameters of :math:`Γ_P`. We have: - -.. inference:: Ind-Family - - \left\{\begin{array}{l} - \ind{p}{Γ_I}{Γ_C} \in E\\ - (E[] ⊢ q_l : P'_l)_{l=1\ldots r}\\ - (E[] ⊢ P'_l ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1})_{l=1\ldots r}\\ - 1 \leq j \leq k - \end{array} - \right. - ----------------------------- - E[] ⊢ I_j~q_1 … q_r :∀ [p_{r+1} :P_{r+1} ;~…;~p_p :P_p], (A_j)_{/s_j} - -provided that the following side conditions hold: - - + :math:`Γ_{P′}` is the context obtained from :math:`Γ_P` by replacing each :math:`P_l` that is - an arity with :math:`P_l'` for :math:`1≤ l ≤ r` (notice that :math:`P_l` arity implies :math:`P_l'` - arity since :math:`E[] ⊢ P_l' ≤_{βδιζη} \subst{P_l}{p_u}{q_u}_{u=1\ldots l-1}`); - + there are sorts :math:`s_i`, for :math:`1 ≤ i ≤ k` such that, for - :math:`Γ_{I'} = [I_1 :∀ Γ_{P'} ,(A_1)_{/s_1} ;~…;~I_k :∀ Γ_{P'} ,(A_k)_{/s_k}]` - we have :math:`(E[Γ_{I′} ;Γ_{P′}] ⊢ C_i : s_{q_i})_{i=1… n}` ; - + the sorts :math:`s_i` are all introduced by the inductive - declaration and have no universe constraints beside being greater - than or equal to :math:`\Prop`, and such that all - eliminations, to :math:`\Prop`, :math:`\Set` and :math:`\Type(j)`, - are allowed (see Section :ref:`Destructors`). - - -Notice that if :math:`I_j~q_1 … q_r` is typable using the rules **Ind-Const** and -**App**, then it is typable using the rule **Ind-Family**. Conversely, the -extended theory is not stronger than the theory without **Ind-Family**. We -get an equiconsistency result by mapping each :math:`\ind{p}{Γ_I}{Γ_C}` -occurring into a given derivation into as many different inductive -types and constructors as the number of different (partial) -replacements of sorts, needed for this derivation, in the parameters -that are arities (this is possible because :math:`\ind{p}{Γ_I}{Γ_C}` well-formed -implies that :math:`\ind{p}{Γ_{I'}}{Γ_{C'}}` is well-formed and has the -same allowed eliminations, where :math:`Γ_{I′}` is defined as above and -:math:`Γ_{C′} = [c_1 :∀ Γ_{P′} ,C_1 ;~…;~c_n :∀ Γ_{P′} ,C_n ]`). That is, the changes in the -types of each partial instance :math:`q_1 … q_r` can be characterized by the -ordered sets of arity sorts among the types of parameters, and to each -signature is associated a new inductive definition with fresh names. -Conversion is preserved as any (partial) instance :math:`I_j~q_1 … q_r` or -:math:`C_i~q_1 … q_r` is mapped to the names chosen in the specific instance of -:math:`\ind{p}{Γ_I}{Γ_C}`. - -.. warning:: - - The restriction that sorts are introduced by the inductive - declaration prevents inductive types declared in sections to be - template-polymorphic on universes introduced previously in the - section: they cannot parameterize over the universes introduced with - section variables that become parameters at section closing time, as - these may be shared with other definitions from the same section - which can impose constraints on them. - -.. flag:: Auto Template Polymorphism - - This flag, enabled by default, makes every inductive type declared - at level :math:`\Type` (without annotations or hiding it behind a - definition) template polymorphic if possible. - - This can be prevented using the :attr:`universes(notemplate)` - attribute. - - Template polymorphism and full universe polymorphism (see Chapter - :ref:`polymorphicuniverses`) are incompatible, so if the latter is - enabled (through the :flag:`Universe Polymorphism` flag or the - :attr:`universes(polymorphic)` attribute) it will prevail over - automatic template polymorphism. - -.. warn:: Automatically declaring @ident as template polymorphic. - - Warning ``auto-template`` can be used (it is off by default) to - find which types are implicitly declared template polymorphic by - :flag:`Auto Template Polymorphism`. - - An inductive type can be forced to be template polymorphic using - the :attr:`universes(template)` attribute: in this case, the - warning is not emitted. - -.. attr:: universes(template) - - This attribute can be used to explicitly declare an inductive type - as template polymorphic, whether the :flag:`Auto Template - Polymorphism` flag is on or off. - - .. exn:: template and polymorphism not compatible - - This attribute cannot be used in a full universe polymorphic - context, i.e. if the :flag:`Universe Polymorphism` flag is on or - if the :attr:`universes(polymorphic)` attribute is used. - - .. exn:: Ill-formed template inductive declaration: not polymorphic on any universe. - - The attribute was used but the inductive definition does not - satisfy the criterion to be template polymorphic. - -.. attr:: universes(notemplate) - - This attribute can be used to prevent an inductive type to be - template polymorphic, even if the :flag:`Auto Template - Polymorphism` flag is on. - -In practice, the rule **Ind-Family** is used by |Coq| only when all the -inductive types of the inductive definition are declared with an arity -whose sort is in the Type hierarchy. Then, the polymorphism is over -the parameters whose type is an arity of sort in the Type hierarchy. -The sorts :math:`s_j` are chosen canonically so that each :math:`s_j` is minimal with -respect to the hierarchy :math:`\Prop ⊂ \Set_p ⊂ \Type` where :math:`\Set_p` is predicative -:math:`\Set`. More precisely, an empty or small singleton inductive definition -(i.e. an inductive definition of which all inductive types are -singleton – see Section :ref:`Destructors`) is set in :math:`\Prop`, a small non-singleton -inductive type is set in :math:`\Set` (even in case :math:`\Set` is impredicative – see -Section The-Calculus-of-Inductive-Construction-with-impredicative-Set_), -and otherwise in the Type hierarchy. - -Note that the side-condition about allowed elimination sorts in the rule -**Ind-Family** avoids to recompute the allowed elimination sorts at each -instance of a pattern matching (see Section :ref:`Destructors`). As an -example, let us consider the following definition: - -.. example:: - - .. coqtop:: in - - Inductive option (A:Type) : Type := - | None : option A - | Some : A -> option A. - -As the definition is set in the Type hierarchy, it is used -polymorphically over its parameters whose types are arities of a sort -in the Type hierarchy. Here, the parameter :math:`A` has this property, hence, -if :g:`option` is applied to a type in :math:`\Set`, the result is in :math:`\Set`. Note that -if :g:`option` is applied to a type in :math:`\Prop`, then, the result is not set in -:math:`\Prop` but in :math:`\Set` still. This is because :g:`option` is not a singleton type -(see Section :ref:`Destructors`) and it would lose the elimination to :math:`\Set` and :math:`\Type` -if set in :math:`\Prop`. - -.. example:: - - .. coqtop:: all - - Check (fun A:Set => option A). - Check (fun A:Prop => option A). - -Here is another example. - -.. example:: - - .. coqtop:: in - - Inductive prod (A B:Type) : Type := pair : A -> B -> prod A B. - -As :g:`prod` is a singleton type, it will be in :math:`\Prop` if applied twice to -propositions, in :math:`\Set` if applied twice to at least one type in :math:`\Set` and -none in :math:`\Type`, and in :math:`\Type` otherwise. In all cases, the three kind of -eliminations schemes are allowed. - -.. example:: - - .. coqtop:: all - - Check (fun A:Set => prod A). - Check (fun A:Prop => prod A A). - Check (fun (A:Prop) (B:Set) => prod A B). - Check (fun (A:Type) (B:Prop) => prod A B). - -.. note:: - Template polymorphism used to be called “sort-polymorphism of - inductive types” before universe polymorphism - (see Chapter :ref:`polymorphicuniverses`) was introduced. - - -.. _Destructors: - -Destructors -~~~~~~~~~~~~~~~~~ - -The specification of inductive definitions with arities and -constructors is quite natural. But we still have to say how to use an -object in an inductive type. - -This problem is rather delicate. There are actually several different -ways to do that. Some of them are logically equivalent but not always -equivalent from the computational point of view or from the user point -of view. - -From the computational point of view, we want to be able to define a -function whose domain is an inductively defined type by using a -combination of case analysis over the possible constructors of the -object and recursion. - -Because we need to keep a consistent theory and also we prefer to keep -a strongly normalizing reduction, we cannot accept any sort of -recursion (even terminating). So the basic idea is to restrict -ourselves to primitive recursive functions and functionals. - -For instance, assuming a parameter :math:`A:\Set` exists in the local context, -we want to build a function :math:`\length` of type :math:`\List~A → \nat` which computes -the length of the list, such that :math:`(\length~(\Nil~A)) = \nO` and -:math:`(\length~(\cons~A~a~l)) = (\nS~(\length~l))`. -We want these equalities to be -recognized implicitly and taken into account in the conversion rule. - -From the logical point of view, we have built a type family by giving -a set of constructors. We want to capture the fact that we do not have -any other way to build an object in this type. So when trying to prove -a property about an object :math:`m` in an inductive type it is enough -to enumerate all the cases where :math:`m` starts with a different -constructor. - -In case the inductive definition is effectively a recursive one, we -want to capture the extra property that we have built the smallest -fixed point of this recursive equation. This says that we are only -manipulating finite objects. This analysis provides induction -principles. For instance, in order to prove -:math:`∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l))` it is enough to prove: - - -+ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~(\length~(\Nil~A)))` -+ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` - :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\length~(\cons~A~a~l)))` - - -which given the conversion equalities satisfied by :math:`\length` is the same -as proving: - - -+ :math:`(\kw{has}\_\kw{length}~A~(\Nil~A)~\nO)` -+ :math:`∀ a:A,~∀ l:\List~A,~(\kw{has}\_\kw{length}~A~l~(\length~l)) →` - :math:`(\kw{has}\_\kw{length}~A~(\cons~A~a~l)~(\nS~(\length~l)))` - - -One conceptually simple way to do that, following the basic scheme -proposed by Martin-Löf in his Intuitionistic Type Theory, is to -introduce for each inductive definition an elimination operator. At -the logical level it is a proof of the usual induction principle and -at the computational level it implements a generic operator for doing -primitive recursion over the structure. - -But this operator is rather tedious to implement and use. We choose in -this version of |Coq| to factorize the operator for primitive recursion -into two more primitive operations as was first suggested by Th. -Coquand in :cite:`Coq92`. One is the definition by pattern matching. The -second one is a definition by guarded fixpoints. - - -.. _match-construction: - -The match ... with ... end construction -+++++++++++++++++++++++++++++++++++++++ - -The basic idea of this operator is that we have an object :math:`m` in an -inductive type :math:`I` and we want to prove a property which possibly -depends on :math:`m`. For this, it is enough to prove the property for -:math:`m = (c_i~u_1 … u_{p_i} )` for each constructor of :math:`I`. -The |Coq| term for this proof -will be written: - -.. math:: - \Match~m~\with~(c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend - -In this expression, if :math:`m` eventually happens to evaluate to -:math:`(c_i~u_1 … u_{p_i})` then the expression will behave as specified in its :math:`i`-th branch -and it will reduce to :math:`f_i` where the :math:`x_{i1} …x_{ip_i}` are replaced by the -:math:`u_1 … u_{p_i}` according to the ι-reduction. - -Actually, for type checking a :math:`\Match…\with…\kwend` expression we also need -to know the predicate :math:`P` to be proved by case analysis. In the general -case where :math:`I` is an inductively defined :math:`n`-ary relation, :math:`P` is a predicate -over :math:`n+1` arguments: the :math:`n` first ones correspond to the arguments of :math:`I` -(parameters excluded), and the last one corresponds to object :math:`m`. |Coq| -can sometimes infer this predicate but sometimes not. The concrete -syntax for describing this predicate uses the :math:`\as…\In…\return` -construction. For instance, let us assume that :math:`I` is an unary predicate -with one parameter and one argument. The predicate is made explicit -using the syntax: - -.. math:: - \Match~m~\as~x~\In~I~\_~a~\return~P~\with~ - (c_1~x_{11} ... x_{1p_1} ) ⇒ f_1 | … - | (c_n~x_{n1} ... x_{np_n} ) ⇒ f_n~\kwend - -The :math:`\as` part can be omitted if either the result type does not depend -on :math:`m` (non-dependent elimination) or :math:`m` is a variable (in this case, :math:`m` -can occur in :math:`P` where it is considered a bound variable). The :math:`\In` part -can be omitted if the result type does not depend on the arguments -of :math:`I`. Note that the arguments of :math:`I` corresponding to parameters *must* -be :math:`\_`, because the result type is not generalized to all possible -values of the parameters. The other arguments of :math:`I` (sometimes called -indices in the literature) have to be variables (:math:`a` above) and these -variables can occur in :math:`P`. The expression after :math:`\In` must be seen as an -*inductive type pattern*. Notice that expansion of implicit arguments -and notations apply to this pattern. For the purpose of presenting the -inference rules, we use a more compact notation: - -.. math:: - \case(m,(λ a x . P), λ x_{11} ... x_{1p_1} . f_1~| … |~λ x_{n1} ...x_{np_n} . f_n ) - - -.. _Allowed-elimination-sorts: - -**Allowed elimination sorts.** An important question for building the typing rule for :math:`\Match` is what -can be the type of :math:`λ a x . P` with respect to the type of :math:`m`. If :math:`m:I` -and :math:`I:A` and :math:`λ a x . P : B` then by :math:`[I:A|B]` we mean that one can use -:math:`λ a x . P` with :math:`m` in the above match-construct. - - -.. _cic_notations: - -**Notations.** The :math:`[I:A|B]` is defined as the smallest relation satisfying the -following rules: We write :math:`[I|B]` for :math:`[I:A|B]` where :math:`A` is the type of :math:`I`. - -The case of inductive types in sorts :math:`\Set` or :math:`\Type` is simple. -There is no restriction on the sort of the predicate to be eliminated. - -.. inference:: Prod - - [(I~x):A′|B′] - ----------------------- - [I:∀ x:A,~A′|∀ x:A,~B′] - - -.. inference:: Set & Type - - s_1 ∈ \{\Set,\Type(j)\} - s_2 ∈ \Sort - ---------------- - [I:s_1 |I→ s_2 ] - - -The case of Inductive definitions of sort :math:`\Prop` is a bit more -complicated, because of our interpretation of this sort. The only -harmless allowed eliminations, are the ones when predicate :math:`P` -is also of sort :math:`\Prop` or is of the morally smaller sort -:math:`\SProp`. - -.. inference:: Prop - - s ∈ \{\SProp,\Prop\} - -------------------- - [I:\Prop|I→s] - - -:math:`\Prop` is the type of logical propositions, the proofs of properties :math:`P` in -:math:`\Prop` could not be used for computation and are consequently ignored by -the extraction mechanism. Assume :math:`A` and :math:`B` are two propositions, and the -logical disjunction :math:`A ∨ B` is defined inductively by: - -.. example:: - - .. coqtop:: in - - Inductive or (A B:Prop) : Prop := - or_introl : A -> or A B | or_intror : B -> or A B. - - -The following definition which computes a boolean value by case over -the proof of :g:`or A B` is not accepted: - -.. example:: - - .. coqtop:: all - - Fail Definition choice (A B: Prop) (x:or A B) := - match x with or_introl _ _ a => true | or_intror _ _ b => false end. - -From the computational point of view, the structure of the proof of -:g:`(or A B)` in this term is needed for computing the boolean value. - -In general, if :math:`I` has type :math:`\Prop` then :math:`P` cannot have type :math:`I→\Set`, because -it will mean to build an informative proof of type :math:`(P~m)` doing a case -analysis over a non-computational object that will disappear in the -extracted program. But the other way is safe with respect to our -interpretation we can have :math:`I` a computational object and :math:`P` a -non-computational one, it just corresponds to proving a logical property -of a computational object. - -In the same spirit, elimination on :math:`P` of type :math:`I→\Type` cannot be allowed -because it trivially implies the elimination on :math:`P` of type :math:`I→ \Set` by -cumulativity. It also implies that there are two proofs of the same -property which are provably different, contradicting the -proof-irrelevance property which is sometimes a useful axiom: - -.. example:: - - .. coqtop:: all - - Axiom proof_irrelevance : forall (P : Prop) (x y : P), x=y. - -The elimination of an inductive type of sort :math:`\Prop` on a predicate -:math:`P` of type :math:`I→ \Type` leads to a paradox when applied to impredicative -inductive definition like the second-order existential quantifier -:g:`exProp` defined above, because it gives access to the two projections on -this type. - - -.. _Empty-and-singleton-elimination: - -**Empty and singleton elimination.** There are special inductive definitions in -:math:`\Prop` for which more eliminations are allowed. - -.. inference:: Prop-extended - - I~\kw{is an empty or singleton definition} - s ∈ \Sort - ------------------------------------- - [I:\Prop|I→ s] - -A *singleton definition* has only one constructor and all the -arguments of this constructor have type :math:`\Prop`. In that case, there is a -canonical way to interpret the informative extraction on an object in -that type, such that the elimination on any sort :math:`s` is legal. Typical -examples are the conjunction of non-informative propositions and the -equality. If there is a hypothesis :math:`h:a=b` in the local context, it can -be used for rewriting not only in logical propositions but also in any -type. - -.. example:: - - .. coqtop:: all - - Print eq_rec. - Require Extraction. - Extraction eq_rec. - -An empty definition has no constructors, in that case also, -elimination on any sort is allowed. - -.. _Eliminaton-for-SProp: - -Inductive types in :math:`\SProp` must have no constructors (i.e. be -empty) to be eliminated to produce relevant values. - -Note that thanks to proof irrelevance elimination functions can be -produced for other types, for instance the elimination for a unit type -is the identity. - -.. _Type-of-branches: - -**Type of branches.** -Let :math:`c` be a term of type :math:`C`, we assume :math:`C` is a type of constructor for an -inductive type :math:`I`. Let :math:`P` be a term that represents the property to be -proved. We assume :math:`r` is the number of parameters and :math:`s` is the number of -arguments. - -We define a new type :math:`\{c:C\}^P` which represents the type of the branch -corresponding to the :math:`c:C` constructor. - -.. math:: - \begin{array}{ll} - \{c:(I~q_1\ldots q_r\ t_1 \ldots t_s)\}^P &\equiv (P~t_1\ldots ~t_s~c) \\ - \{c:∀ x:T,~C\}^P &\equiv ∀ x:T,~\{(c~x):C\}^P - \end{array} - -We write :math:`\{c\}^P` for :math:`\{c:C\}^P` with :math:`C` the type of :math:`c`. - - -.. example:: - - The following term in concrete syntax:: - - match t as l return P' with - | nil _ => t1 - | cons _ hd tl => t2 - end - - - can be represented in abstract syntax as - - .. math:: - \case(t,P,f_1 | f_2 ) - - where - - .. math:: - :nowrap: - - \begin{eqnarray*} - P & = & λ l.~P^\prime\\ - f_1 & = & t_1\\ - f_2 & = & λ (hd:\nat).~λ (tl:\List~\nat).~t_2 - \end{eqnarray*} - - According to the definition: - - .. math:: - \{(\Nil~\nat)\}^P ≡ \{(\Nil~\nat) : (\List~\nat)\}^P ≡ (P~(\Nil~\nat)) - - .. math:: - - \begin{array}{rl} - \{(\cons~\nat)\}^P & ≡\{(\cons~\nat) : (\nat→\List~\nat→\List~\nat)\}^P \\ - & ≡∀ n:\nat,~\{(\cons~\nat~n) : (\List~\nat→\List~\nat)\}^P \\ - & ≡∀ n:\nat,~∀ l:\List~\nat,~\{(\cons~\nat~n~l) : (\List~\nat)\}^P \\ - & ≡∀ n:\nat,~∀ l:\List~\nat,~(P~(\cons~\nat~n~l)). - \end{array} - - Given some :math:`P` then :math:`\{(\Nil~\nat)\}^P` represents the expected type of :math:`f_1`, - and :math:`\{(\cons~\nat)\}^P` represents the expected type of :math:`f_2`. - - -.. _Typing-rule: - -**Typing rule.** -Our very general destructor for inductive definition enjoys the -following typing rule - -.. inference:: match - - \begin{array}{l} - E[Γ] ⊢ c : (I~q_1 … q_r~t_1 … t_s ) \\ - E[Γ] ⊢ P : B \\ - [(I~q_1 … q_r)|B] \\ - (E[Γ] ⊢ f_i : \{(c_{p_i}~q_1 … q_r)\}^P)_{i=1… l} - \end{array} - ------------------------------------------------ - E[Γ] ⊢ \case(c,P,f_1 |… |f_l ) : (P~t_1 … t_s~c) - -provided :math:`I` is an inductive type in a -definition :math:`\ind{r}{Γ_I}{Γ_C}` with :math:`Γ_C = [c_1 :C_1 ;~…;~c_n :C_n ]` and -:math:`c_{p_1} … c_{p_l}` are the only constructors of :math:`I`. - - - -.. example:: - - Below is a typing rule for the term shown in the previous example: - - .. inference:: list example - - \begin{array}{l} - E[Γ] ⊢ t : (\List ~\nat) \\ - E[Γ] ⊢ P : B \\ - [(\List ~\nat)|B] \\ - E[Γ] ⊢ f_1 : \{(\Nil ~\nat)\}^P \\ - E[Γ] ⊢ f_2 : \{(\cons ~\nat)\}^P - \end{array} - ------------------------------------------------ - E[Γ] ⊢ \case(t,P,f_1 |f_2 ) : (P~t) - - -.. _Definition-of-ι-reduction: - -**Definition of ι-reduction.** -We still have to define the ι-reduction in the general case. - -An ι-redex is a term of the following form: - -.. math:: - \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) - -with :math:`c_{p_i}` the :math:`i`-th constructor of the inductive type :math:`I` with :math:`r` -parameters. - -The ι-contraction of this term is :math:`(f_i~a_1 … a_m )` leading to the -general reduction rule: - -.. math:: - \case((c_{p_i}~q_1 … q_r~a_1 … a_m ),P,f_1 |… |f_l ) \triangleright_ι (f_i~a_1 … a_m ) - - -.. _Fixpoint-definitions: - -Fixpoint definitions -~~~~~~~~~~~~~~~~~~~~ - -The second operator for elimination is fixpoint definition. This -fixpoint may involve several mutually recursive definitions. The basic -concrete syntax for a recursive set of mutually recursive declarations -is (with :math:`Γ_i` contexts): - -.. math:: - \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n - - -The terms are obtained by projections from this set of declarations -and are written - -.. math:: - \fix~f_1 (Γ_1 ) :A_1 :=t_1~\with … \with~f_n (Γ_n ) :A_n :=t_n~\for~f_i - -In the inference rules, we represent such a term by - -.. math:: - \Fix~f_i\{f_1 :A_1':=t_1' … f_n :A_n':=t_n'\} - -with :math:`t_i'` (resp. :math:`A_i'`) representing the term :math:`t_i` abstracted (resp. -generalized) with respect to the bindings in the context :math:`Γ_i`, namely -:math:`t_i'=λ Γ_i . t_i` and :math:`A_i'=∀ Γ_i , A_i`. - - -Typing rule -+++++++++++ - -The typing rule is the expected one for a fixpoint. - -.. inference:: Fix - - (E[Γ] ⊢ A_i : s_i )_{i=1… n} - (E[Γ;~f_1 :A_1 ;~…;~f_n :A_n ] ⊢ t_i : A_i )_{i=1… n} - ------------------------------------------------------- - E[Γ] ⊢ \Fix~f_i\{f_1 :A_1 :=t_1 … f_n :A_n :=t_n \} : A_i - - -Any fixpoint definition cannot be accepted because non-normalizing -terms allow proofs of absurdity. The basic scheme of recursion that -should be allowed is the one needed for defining primitive recursive -functionals. In that case the fixpoint enjoys a special syntactic -restriction, namely one of the arguments belongs to an inductive type, -the function starts with a case analysis and recursive calls are done -on variables coming from patterns and representing subterms. For -instance in the case of natural numbers, a proof of the induction -principle of type - -.. math:: - ∀ P:\nat→\Prop,~(P~\nO)→(∀ n:\nat,~(P~n)→(P~(\nS~n)))→ ∀ n:\nat,~(P~n) - -can be represented by the term: - -.. math:: - \begin{array}{l} - λ P:\nat→\Prop.~λ f:(P~\nO).~λ g:(∀ n:\nat,~(P~n)→(P~(\nS~n))).\\ - \Fix~h\{h:∀ n:\nat,~(P~n):=λ n:\nat.~\case(n,P,f | λp:\nat.~(g~p~(h~p)))\} - \end{array} - -Before accepting a fixpoint definition as being correctly typed, we -check that the definition is “guarded”. A precise analysis of this -notion can be found in :cite:`Gim94`. The first stage is to precise on which -argument the fixpoint will be decreasing. The type of this argument -should be an inductive type. For doing this, the syntax of -fixpoints is extended and becomes - -.. math:: - \Fix~f_i\{f_1/k_1 :A_1:=t_1 … f_n/k_n :A_n:=t_n\} - - -where :math:`k_i` are positive integers. Each :math:`k_i` represents the index of -parameter of :math:`f_i`, on which :math:`f_i` is decreasing. Each :math:`A_i` should be a -type (reducible to a term) starting with at least :math:`k_i` products -:math:`∀ y_1 :B_1 ,~… ∀ y_{k_i} :B_{k_i} ,~A_i'` and :math:`B_{k_i}` an inductive type. - -Now in the definition :math:`t_i`, if :math:`f_j` occurs then it should be applied to -at least :math:`k_j` arguments and the :math:`k_j`-th argument should be -syntactically recognized as structurally smaller than :math:`y_{k_i}`. - -The definition of being structurally smaller is a bit technical. One -needs first to define the notion of *recursive arguments of a -constructor*. For an inductive definition :math:`\ind{r}{Γ_I}{Γ_C}`, if the -type of a constructor :math:`c` has the form -:math:`∀ p_1 :P_1 ,~… ∀ p_r :P_r,~∀ x_1:T_1,~… ∀ x_m :T_m,~(I_j~p_1 … p_r~t_1 … t_s )`, -then the recursive -arguments will correspond to :math:`T_i` in which one of the :math:`I_l` occurs. - -The main rules for being structurally smaller are the following. -Given a variable :math:`y` of an inductively defined type in a declaration -:math:`\ind{r}{Γ_I}{Γ_C}` where :math:`Γ_I` is :math:`[I_1 :A_1 ;~…;~I_k :A_k]`, and :math:`Γ_C` is -:math:`[c_1 :C_1 ;~…;~c_n :C_n ]`, the terms structurally smaller than :math:`y` are: - - -+ :math:`(t~u)` and :math:`λ x:U .~t` when :math:`t` is structurally smaller than :math:`y`. -+ :math:`\case(c,P,f_1 … f_n)` when each :math:`f_i` is structurally smaller than :math:`y`. - If :math:`c` is :math:`y` or is structurally smaller than :math:`y`, its type is an inductive - type :math:`I_p` part of the inductive definition corresponding to :math:`y`. - Each :math:`f_i` corresponds to a type of constructor - :math:`C_q ≡ ∀ p_1 :P_1 ,~…,∀ p_r :P_r ,~∀ y_1 :B_1 ,~… ∀ y_m :B_m ,~(I_p~p_1 … p_r~t_1 … t_s )` - and can consequently be written :math:`λ y_1 :B_1' .~… λ y_m :B_m'.~g_i`. (:math:`B_i'` is - obtained from :math:`B_i` by substituting parameters for variables) the variables - :math:`y_j` occurring in :math:`g_i` corresponding to recursive arguments :math:`B_i` (the - ones in which one of the :math:`I_l` occurs) are structurally smaller than :math:`y`. - - -The following definitions are correct, we enter them using the :cmd:`Fixpoint` -command and show the internal representation. - -.. example:: - - .. coqtop:: all - - Fixpoint plus (n m:nat) {struct n} : nat := - match n with - | O => m - | S p => S (plus p m) - end. - - Print plus. - Fixpoint lgth (A:Set) (l:list A) {struct l} : nat := - match l with - | nil _ => O - | cons _ a l' => S (lgth A l') - end. - Print lgth. - Fixpoint sizet (t:tree) : nat := let (f) := t in S (sizef f) - with sizef (f:forest) : nat := - match f with - | emptyf => O - | consf t f => plus (sizet t) (sizef f) - end. - Print sizet. - -.. _Reduction-rule: - -Reduction rule -++++++++++++++ - -Let :math:`F` be the set of declarations: -:math:`f_1 /k_1 :A_1 :=t_1 …f_n /k_n :A_n:=t_n`. -The reduction for fixpoints is: - -.. math:: - (\Fix~f_i \{F\}~a_1 …a_{k_i}) ~\triangleright_ι~ \subst{t_i}{f_k}{\Fix~f_k \{F\}}_{k=1… n} ~a_1 … a_{k_i} - -when :math:`a_{k_i}` starts with a constructor. This last restriction is needed -in order to keep strong normalization and corresponds to the reduction -for primitive recursive operators. The following reductions are now -possible: - -.. math:: - :nowrap: - - \begin{eqnarray*} - \plus~(\nS~(\nS~\nO))~(\nS~\nO)~& \trii & \nS~(\plus~(\nS~\nO)~(\nS~\nO))\\ - & \trii & \nS~(\nS~(\plus~\nO~(\nS~\nO)))\\ - & \trii & \nS~(\nS~(\nS~\nO))\\ - \end{eqnarray*} - -.. _Mutual-induction: - -**Mutual induction** - -The principles of mutual induction can be automatically generated -using the Scheme command described in Section :ref:`proofschemes-induction-principles`. - - .. _Admissible-rules-for-global-environments: Admissible rules for global environments -- cgit v1.2.3