6.5. リテラル(Literals)

数値リテラルには2種類あります:自然数リテラルと 科学的リテラル (scientific literal)です。どちらも 型クラス によってオーバーロードされます。

6.5.1. 自然数(Natural Numbers)🔗

Lean は自然数リテラル n に遭遇すると、オーバーロードされたメソッド OfNat.ofNat n によってそれを解釈します。 OfNat Nat nデフォルトインスタンス は他の型情報が存在しない時に Nat の型を推論できることを保証します。

🔗type class
OfNat.{u} (α : Type u) : NatType u

The class OfNat α n powers the numeric literal parser. If you write 37 : α, Lean will attempt to synthesize OfNat α 37, and will generate the term (OfNat.ofNat 37 : α).

There is a bit of infinite regress here since the desugaring apparently still contains a literal 37 in it. The type of expressions contains a primitive constructor for "raw natural number literals", which you can directly access using the macro nat_lit 37. Raw number literals are always of type Nat. So it would be more correct to say that Lean looks for an instance of OfNat α (nat_lit 37), and it generates the term (OfNat.ofNat (nat_lit 37) : α).

Instance Constructor

OfNat.mk.{u}

Methods

ofNat : α

The OfNat.ofNat function is automatically inserted by the parser when the user writes a numeric literal like 1 : α. Implementations of this typeclass can therefore customize the behavior of n : α based on n and α.

カスタムの自然数リテラル

構造体 NatInterval は自然数の区間を表します。

structure NatInterval where low : Nat high : Nat low_le_high : low high instance : Add NatInterval where add | lo1, hi1, le1, lo2, hi2, le2 => lo1 + lo2, hi1 + hi2, lo1:Nathi1:Natle1:lo1hi1lo2:Nathi2:Natle2:lo2hi2lo1 + lo2hi1 + hi2 All goals completed! 🐙

OfNat インスタンスによって、自然数リテラルを使って区間を表すことができます:

instance : OfNat NatInterval n where ofNat := n, n, n:Natnn All goals completed! 🐙 { low := 8, high := 8, low_le_high := _ }#eval (8 : NatInterval)
{ low := 8, high := 8, low_le_high := _ }

整数リテラルという独立したものはありません。 -5 のような項は、自然数リテラルに適用される前置否定( Neg 型クラスでオーバーロード可能)で構成されます。

6.5.2. 科学的数値(Scientific Numbers)

科学的数値リテラルは、数字列の後ろにピリオド(任意)・小数部・指数(任意)が続くものです。ピリオドや指数が無い場合は、自然数リテラルになります。科学的数値は OfScientific 型クラスによってオーバーロードされます。

🔗type class
OfScientific.{u} (α : Type u) : Type u

For decimal and scientific numbers (e.g., 1.23, 3.12e10). Examples:

Note the use of nat_lit; there is no wrapping OfNat.ofNat in the resulting term.

Instance Constructor

OfScientific.mk.{u}

Methods

ofScientific : NatBoolNatα

Float に対する OfScientific インスタンスはありますが、個別の浮動小数点リテラルはありません。 訳注:16, 32, 64bitのそれぞれの精度の浮動小数点に対して存在しないという意味と思われる。

6.5.3. 文字列(Strings)

文字列リテラルは 文字列の章 で説明されています。

6.5.4. リストと配列(Lists and Arrays)

リストと配列は、カンマで区切られたカッコ内の要素の列として構成されます。配列の場合はハッシュマーク(#)を先頭に付けます。配列リテラルは、変換の呼び出しでラップされたリストリテラルとして解釈されます。パフォーマンス上の理由から、非常に大きなリストや配列リテラルは、リストコンストラクタの繰り返し適用ではなく、ローカル定義の列に変換されます。

syntaxList Literals
term ::= ...
    | The syntax `[a, b, c]` is shorthand for `a :: b :: c :: []`, or
`List.cons a (List.cons b (List.cons c List.nil))`. It allows conveniently constructing
list literals.

For lists of length at least 64, an alternative desugaring strategy is used
which uses let bindings as intermediates as in
`let left := [d, e, f]; a :: b :: c :: left` to avoid creating very deep expressions.
Note that this changes the order of evaluation, although it should not be observable
unless you use side effecting operations like `dbg_trace`.
[term,*]
syntaxArray Literals
term ::= ...
    | #[term,*]
長いリストリテラル

このリストは32個の要素を含みます。生成されたコードは List.cons を繰り返し適用したものです:

[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] : List Nat#check [1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] : List Nat

33個の要素を持つリストリテラルは、ローカル定義の列になります:

let y := let y := let y := [1, 1, 1, 1, 1]; 1 :: 1 :: 1 :: 1 :: y; let y := 1 :: 1 :: 1 :: 1 :: y; 1 :: 1 :: 1 :: 1 :: y; let y := let y := 1 :: 1 :: 1 :: 1 :: y; 1 :: 1 :: 1 :: 1 :: y; let y := 1 :: 1 :: 1 :: 1 :: y; 1 :: 1 :: 1 :: 1 :: y : List Nat#check [1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1]
let y :=
  let y :=
    let y := [1, 1, 1, 1, 1];
    1 :: 1 :: 1 :: 1 :: y;
  let y := 1 :: 1 :: 1 :: 1 :: y;
  1 :: 1 :: 1 :: 1 :: y;
let y :=
  let y := 1 :: 1 :: 1 :: 1 :: y;
  1 :: 1 :: 1 :: 1 :: y;
let y := 1 :: 1 :: 1 :: 1 :: y;
1 :: 1 :: 1 :: 1 :: y : List Nat