#loogle

#loogle コマンドは、Lean で定理や関数を探すための検索エンジンである、Loogle を利用した検索をエディタ上で行うためのコマンドです。Loogle で使用できるのと同様の検索クエリが使用できます。

#find と似ていますが、#find と違って #loogle はAPIを利用するだけなのでより高速に動作します。

検索クエリの書き方

名前に特定の文字列が含まれるかどうか

二重引用符 " で文字列を囲って与えると、補題の名前にその文字列が含まれるような補題や、関数名にその文字列が含まれるような関数を検索します。

たとえば、仮に Nat.add_zero : ∀ n : Nat, n + 0 = 0 の名前をどわすれして、思い出したいとしましょう。ここで「整数の、ゼロの和に関する定理」というところまで思い出せるのであれば、定理名に入っていそうな文字列を与えることで検索に引っかけることができます。

import LeanSearchClient.LoogleSyntax

/-
info: Loogle Search Results
  • #check Nat.add_zero --  (n : ℕ) : n + 0 = n
    ⏎
  • #check instNeZeroNatHAdd --  {n m : ℕ} [h : NeZero n] : NeZero (n + m)
    ⏎
  • #check instNeZeroNatHAdd_1 --  {n m : ℕ} [h : NeZero m] : NeZero (n + m)
    ⏎
  • #check Nat.zero_add --  (n : ℕ) : 0 + n = n
    ⏎
  • #check Nat.add_one_ne_zero --  (n : ℕ) : n + 1 ≠ 0
    ⏎
  • #check Nat.zero_ne_add_one --  (n : ℕ) : 0 ≠ n + 1
-/
#loogle "Nat", "zero", "add"

特定の定数・関数が登場するか

たとえば List.foldl という関数についてどのような補題が存在するか知りたいとします。このような場合、List.foldl が定理の中で言及されているような定理を検索したいですが、これはそのまま識別子を与えることで検索可能です。

/-
info: Loogle Search Results
  • #check List.foldl --  {α : Type u} {β : Type v} (f : α → β → α) (init : α) : List β → α
    Folds a function over a list from the left, accumulating a value starting with `init`. The
    accumulated value is combined with the each element of the list in order, using `f`.
    ⏎
    Examples:
     * `[a, b, c].foldl f z  = f (f (f z a) b) c`
     * `[1, 2, 3].foldl (· ++ toString ·) "" = "123"`
     * `[1, 2, 3].foldl (s!"({·} {·})") "" = "((( 1) 2) 3)"`
    ⏎
    ⏎
  • #check List.foldl_nil --  {α✝ : Type u_1} {β✝ : Type u_2} {f : α✝ → β✝ → α✝} {b : α✝} : List.foldl f b [] = b
    ⏎
  • #check List.foldl_cons --  {α : Type u} {β : Type v} {a : α} {l : List α} {f : β → α → β} {b : β} : List.foldl f b (a :: l) = List.foldl f (f b a) l
    ⏎
  • #check List.id_run_foldlM --  {β : Type u_1} {α : Type u_2} {f : β → α → Id β} {b : β} {l : List α} : (List.foldlM f b l).run = List.foldl f b l
    ⏎
  • #check List.foldl_eq_foldr_reverse --  {α : Type u_1} {β : Type u_2} {l : List α} {f : β → α → β} {b : β} : List.foldl f b l = List.foldr (fun x y => f y x) b l.reverse
    ⏎
  • #check List.foldl_reverse --  {α : Type u_1} {β : Type u_2} {l : List α} {f : β → α → β} {b : β} : List.foldl f b l.reverse = List.foldr (fun x y => f y x) b l
-/
#loogle List.foldl

型による検索

探したい定理・関数が持っているはずの型で検索することができます。たとえば List.map という関数をどわすれしたとしましょう。このとき、(α → β) → List α → List β という型を持つ関数を探すことで、List.map にたどり着くことができます。それには型変数の部分をメタ変数にして検索クエリを作ります。

/-
info: Loogle Search Results
  • #check List.modifyHead --  {α : Type u} (f : α → α) : List α → List α
    Replace the head of the list with the result of applying `f` to it. Returns the empty list if the
    list is empty.
    ⏎
    Examples:
     * `[1, 2, 3].modifyHead (· * 10) = [10, 2, 3]`
     * `[].modifyHead (· * 10) = []`
    ⏎
    ⏎
  • #check List.map --  {α : Type u} {β : Type v} (f : α → β) (l : List α) : List β
    Applies a function to each element of the list, returning the resulting list of values.
    ⏎
    `O(|l|)`.
    ⏎
    Examples:
    * `[a, b, c].map f = [f a, f b, f c]`
    * `[].map Nat.succ = []`
    * `["one", "two", "three"].map (·.length) = [3, 3, 5]`
    * `["one", "two", "three"].map (·.reverse) = ["eno", "owt", "eerht"]`
    ⏎
    ⏎
  • #check List.mapTR --  {α : Type u} {β : Type v} (f : α → β) (as : List α) : List β
    Applies a function to each element of the list, returning the resulting list of values.
    ⏎
    `O(|l|)`. This is the tail-recursive variant of `List.map`, used in runtime code.
    ⏎
    Examples:
    * `[a, b, c].mapTR f = [f a, f b, f c]`
    * `[].mapTR Nat.succ = []`
    * `["one", "two", "three"].mapTR (·.length) = [3, 3, 5]`
    * `["one", "two", "three"].mapTR (·.reverse) = ["eno", "owt", "eerht"]`
    ⏎
    ⏎
  • #check List.modify --  {α : Type u} (l : List α) (i : ℕ) (f : α → α) : List α
    Replaces the element at the given index, if it exists, with the result of applying `f` to it. If the
    index is invalid, the list is returned unmodified.
    ⏎
    Examples:
     * `[1, 2, 3].modify 0 (· * 10) = [10, 2, 3]`
     * `[1, 2, 3].modify 2 (· * 10) = [1, 2, 30]`
     * `[1, 2, 3].modify 3 (· * 10) = [1, 2, 3]`
    ⏎
    ⏎
  • #check List.mapTR.loop --  {α : Type u} {β : Type v} (f : α → β) : List α → List β → List β
    ⏎
  • #check List.map_eq_mapTR --  : @List.map = @List.mapTR
-/
#loogle (?a → ?b) → List ?a → List ?b

パターンによる検索

パターンで検索することもできます。たとえば、n * m = 0 ↔ n = 0 ∨ m = 0 を主張する定理の名前が知りたいとしましょう。このとき、定理の中に出現するべきパターンから検索することができます。

/-
info: Loogle Search Results
  • #check Nat.mul_eq_zero --  {m n : ℕ} : n * m = 0 ↔ n = 0 ∨ m = 0
-/
#loogle "Nat", "mul", (_ * _ = 0), (_ = 0 ∨ _ = 0)