Preámbulo · Lean desde cero
Tipos que se construyen
¿De dónde salen Nat y Bool? No son primitivos misteriosos del sistema: están declarados
en la biblioteca de Lean, con la misma orden que cualquier usuario puede usar. La orden se
llama inductive, y su filosofía cabe en una frase: un tipo es su lista de maneras de
construir elementos. El caso más pequeño posible:
inductive Bool where | true | falseEsto declara un tipo nuevo, Bool, y afirma tres cosas a la vez: true es un Bool,
false es un Bool, y no hay más elementos que esos. La cláusula de cierre (nada es un
Bool salvo lo construido por la lista) no se escribe: es parte del significado de
inductive. Cada línea con | es un constructor, y el tipo queda completamente
determinado por sus constructores.
Peano en tres líneas
El mismo mecanismo, con un giro, produce los naturales:
inductive Nat where | zero | succ (n : Nat)Léase junto a los axiomas de Peano que todo matemático conoce: « es un natural; el
sucesor de un natural es un natural; nada más lo es». Las tres cláusulas son, línea por
línea, la declaración: zero es el cero, succ toma un Nat ya construido y produce otro
(el constructor puede mencionar al propio tipo que se está definiendo, de ahí el nombre
tipo inductivo ), y la cláusula de exclusión viene
gratis. El 3 de las páginas anteriores es, por dentro, succ (succ (succ zero)): los
numerales son abreviaturas.
Que un sistema de axiomas se convierta en una declaración de datos no es un truco de notación. Es el corazón del diseño de Lean: los objetos matemáticos básicos se construyen, no se postulan, y de la construcción Lean extrae automáticamente el principio de inducción correspondiente. La ruta teórica desarrolla esto con rigor; aquí basta ver el patrón.
Desarmar lo construido: match
Si todo Nat viene de zero o de succ, entonces para definir una función sobre Nat
basta decir qué hacer en cada caso. La orden es match:
def doble (n : Nat) : Nat := match n with | Nat.zero => Nat.zero | Nat.succ k => Nat.succ (Nat.succ (doble k))El match distingue por constructor: si n es zero, el doble es zero; si n es
succ k (el sucesor de algún k), el doble es el doble de k más dos sucesores. La
definición se llama a sí misma sobre k: es una definición recursiva, la contraparte
computacional de la inducción.
Aquí hay que ser honestos: no toda «definición» recursiva define algo. Una función que se
llama a sí misma sobre el mismo argumento no termina nunca y no define función alguna. Lean
verifica la terminación: acepta doble porque la llamada recursiva es sobre k,
estrictamente más pequeño que succ k, y rechaza las recursiones que no puede ver
decrecer. Esta vigilancia no es pedantería: si Lean aceptara definiciones que no terminan,
podría «demostrarse» cualquier cosa, y el asistente perdería todo su valor. En la tesis, el
capítulo de completitud depende de una recursión cuya terminación es un teorema en sí mismo.
El anticipo: las fórmulas de la tesis
Todo este preámbulo apunta a un objetivo concreto, y aquí aparece por primera vez. La tesis formaliza la lógica proposicional, y su primer archivo declara qué es una fórmula:
inductive Formula where | atom (n : Nat) | neg (φ : Formula) | impl (φ ψ : Formula)Léase con los ojos ya entrenados: una fórmula es una variable atómica (numerada por un
Nat), o la negación de una fórmula ya construida, o la implicación de dos de ellas. Y nada más lo es. La definición «el conjunto de fórmulas es el
menor conjunto tal que…», que en un libro de lógica ocupa un párrafo cuidadoso, es una
declaración de datos de cuatro líneas, del mismo género que Nat. Las fórmulas de la
lógica son un tipo de datos como los naturales, y las funciones sobre fórmulas (evaluar,
sustituir, medir) se definirán con match, como doble. Este es, literalmente, el archivo
Syntax.lean de la tesis.
El laboratorio del preámbulo no admite tipos declarados por el usuario, así que esta página es de lectura. Todo el código mostrado es Lean 4 legítimo y puede pegarse tal cual en una instalación real o en live.lean-lang.org.
Lo que ya sabes
inductivedeclara un tipo dando su lista de constructores; el tipo es esa lista, y nada fuera de ella habita el tipo.- Los axiomas de Peano son la declaración de
Nat:zeroysucc, con la exclusión incluida de fábrica. matchdefine funciones por casos sobre los constructores; la recursión está permitida y Lean verifica que termina.- Las fórmulas de la lógica proposicional son un tipo inductivo de tres constructores: el primer archivo de la tesis.
Los tipos vistos hasta ahora clasifican datos: números, valores de verdad, funciones, fórmulas. La página siguiente presenta el giro que hace de Lean un asistente de pruebas y no solo un lenguaje: tipos que clasifican afirmaciones.