decide — Decidable Propositions
decide proves decidable propositions by computation. If Lean can compute whether something is true or false, decide handles it.
What is Decidability?
A proposition is decidable if there's an algorithm to determine whether it's true or false. Lean has aDecidable typeclass for this:
lean
1-- The Decidable typeclass2#check @Decidable3-- class Decidable (p : Prop) where4-- decide : Bool5-- -- with proof that decide = true ↔ p67-- Many propositions are decidable8#check (inferInstance : Decidable (2 + 2 = 4))9#check (inferInstance : Decidable (5 < 10))10#check (inferInstance : Decidable ([1, 2, 3].contains 2))Key Takeaway
decide works on any proposition with aDecidable instance. It evaluates the decision procedure and uses the result as a proof.Basic Usage
lean
1-- Numeric comparisons2example : 2 + 2 = 4 := by decide3example : 10 > 5 := by decide4example : 100 % 7 = 2 := by decide56-- Boolean conditions7example : true ∧ true := by decide8example : ¬false := by decide9example : true ∨ false := by decide1011-- List operations12example : [1, 2, 3].length = 3 := by decide13example : [1, 2, 3].contains 2 = true := by decide14example : [1, 2].head? = some 1 := by decidedecide vs rfl
lean
1-- rfl: definitional equality (computation)2example : 2 + 2 = 4 := rfl34-- decide: also works, but through Decidable5example : 2 + 2 = 4 := by decide67-- decide can prove more than rfl8example : ¬(3 = 5) := by decide -- decide works9-- example : ¬(3 = 5) := rfl -- rfl wouldn't work directly1011-- rfl is lighter, decide is more powerful12example : 1 < 2 := by decide13-- example : 1 < 2 := rfl -- wouldn't work (< isn't definitional)Decidable Instances
lean
1-- Many standard types have Decidable instances23-- Equality on basic types4example : "hello" = "hello" := by decide5example : 'a' = 'a' := by decide67-- Comparisons on Nat, Int8example : (5 : Nat) ≤ 10 := by decide9example : ((-3) : Int) < 0 := by decide1011-- List membership (for Decidable equality elements)12example : 3 ∈ [1, 2, 3, 4] := by decide13example : 5 ∉ [1, 2, 3, 4] := by decide1415-- Option16example : (some 5 : Option Nat) ≠ none := by decideℹ
decide runs at kernel level—it actually computes the answer. This means it can be slow for large computations.When decide Fails
lean
1-- Variables aren't decidable (can't compute)2-- example (n : Nat) : n = n := by decide -- fails3example (n : Nat) : n = n := rfl -- use rfl instead45-- Functions without Decidable equality6-- example (f g : Nat → Nat) : f = f := by decide -- fails78-- Propositions without Decidable instance9-- example (P : Prop) : P ∨ ¬P := by decide -- fails (classical)native_decide
native_decide uses compiled native code for faster computation:
lean
1-- native_decide is faster for large computations2example : (List.range 1000).length = 1000 := by native_decide34-- Primality testing5example : Nat.Prime 97 := by native_decide6example : ¬Nat.Prime 100 := by native_decide78-- Large list operations9example : (List.range 100).sum = 4950 := by native_decide⚠
native_decide trusts the compiler—it doesn't verify the computation in the kernel. Use decidefor critical proofs.Deep Dive: How decide Works
decide extracts a proof from aDecidable instance:
lean
1-- Decidable provides a Bool and a proof2-- If the Bool is true, we get a proof of p3-- If false, we get a proof of ¬p45-- decide uses this:6#check @of_decide_eq_true7-- of_decide_eq_true : decide p = true → p89-- So decide:10-- 1. Evaluates "decide p" to true or false11-- 2. If true, applies of_decide_eq_true12-- 3. If false, applies of_decide_eq_false to prove ¬pCustom Decidable Instances
lean
1-- Define your own decidable propositions2structure Person where3 name : String4 age : Nat5deriving DecidableEq -- auto-generate Decidable (a = b)67example : (Person.mk "Alice" 30) = (Person.mk "Alice" 30) := by decide8example : (Person.mk "Alice" 30) ≠ (Person.mk "Bob" 25) := by decide910-- Custom decidable predicate11def isEven (n : Nat) : Bool := n % 2 = 01213instance : Decidable (isEven n = true) := 14 inferInstance -- Bool equality is decidable1516example : isEven 4 = true := by decideExamples
Finite Verification
lean
1-- Check a property for specific values2example : ∀ n ∈ [0, 1, 2, 3, 4], n < 5 := by decide34-- Verify a small theorem instance5example : ∀ a ∈ [true, false], ∀ b ∈ [true, false], a && b = b && a := by decideArray Bounds
lean
1-- Prove array operations are valid2def myArray : Array Nat := #[1, 2, 3, 4, 5]34example : myArray.size = 5 := by decide5example : myArray[0]! = 1 := by native_decideString Operations
lean
1example : "hello".length = 5 := by decide2example : "hello".startsWith "hel" := by decide3example : "world".contains 'o' := by decide