lean2/doc/lean/declarations.org

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