see issue #576
2.9 KiB
Lean declarations
Definitions
The command definition
declares a new constant/function. The identity function is defined as
definition id {A : Type} (a : A) : A := a
We say definitions are "transparent", because the type checker can
unfold them. The following declaration only type checks because +
is
a transparent definition. Otherwise, the type checker would reject
the expression v = w
since it would not be able to establish that
2+3
and 5
are "identical". In type theory, we say they are
definitionally equal.
import data.vector data.nat
open nat
check λ (v : vector nat (2+3)) (w : vector nat 5), v = w
Similarly, the following definition only type checks because id
is transparent, and the type checker can establish that
nat
and id nat
are definitionally equal, that is, they are the "same".
import data.nat
definition id {A : Type} (a : A) : A := a
check λ (x : nat) (y : id nat), x = y
Theorems
In Lean, a theorem is just an opaque
definition. We usually use
theorem
for declaring propositions. The idea is that users don't
really care about the actual proof, only about its existence. As
described in previous sections, Prop
(the type of all propositions)
is proof irrelevant. If we had defined id
using a theorem the
previous example would produce a typing error because the type checker
would be unable to unfold id
and establish that nat
and id nat
are definitionally equal.
Private definitions and theorems
Sometimes it is useful to hide auxiliary definitions and theorems from
the module interface. The keyword private
allows us to declare local
hidden definitions and theorems. A private definition is always
opaque. The name of a private
definition is only visible in the
module/file where it was declared.
import data.nat
open nat
private definition inc (x : nat) := x + 1
private theorem inc_eq_succ (x : nat) : succ x = inc x :=
rfl
-- The definition inc and theorem inc_eq_succ are not visible/accessible
-- in modules that import this one.
Protected definitions and theorems
Declarations can be be organized into namespaces. In the previous
examples, we have been using the namespace nat
. It contains
definitions such as nat.succ
and nat.add
. The command open
creates the aliases succ
and add
to these definitions. An alias
will not be created for a protected definition unless the user
explicitly request it.
import data.nat
open nat
namespace foo
definition two : nat := 2
protected definition three : nat := 3
end foo
open foo
check two
-- The following command produces a 'unknown identifier' error
/-
check three
-/
-- We have to use its fully qualified name to access three
check foo.three
-- If the user explicitly request three, then an alias is created
open foo (three)
check three