Functional Programming in Lean

Interlude: Propositions, Proofs, and Indexing๐Ÿ”—

๋งŽ์€ ์–ธ์–ด์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Lean์€ ๋ฐฐ์—ด๊ณผ ๋ฆฌ์ŠคํŠธ์˜ ์ธ๋ฑ์‹ฑ์— ๋Œ€๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด woodlandCritters๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•˜์ž.

def woodlandCritters : List String := ["hedgehog", "deer", "snail"]

๊ทธ๋Ÿฌ๋ฉด ๊ฐ ์›์†Œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

def hedgehog := woodlandCritters[0] def deer := woodlandCritters[1] def snail := woodlandCritters[2]

๊ทธ๋Ÿฌ๋‚˜ ๋„ค ๋ฒˆ์งธ ์›์†Œ๋ฅผ ์ถ”์ถœํ•˜๋ ค ํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๊ฐ€ ์•„๋‹ˆ๋ผ ์ปดํŒŒ์ผ ํƒ€์ž„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

def oops := failed to prove index is valid, possible solutions: - Use `have`-expressions to prove the index is valid - Use `a[i]!` notation instead, runtime check is performed, and 'Panic' error message is produced if index is not valid - Use `a[i]?` notation instead, result is an `Option` type - Use `a[i]'h` notation instead, where `h` is a proof that index is valid โŠข 3 < woodlandCritters.lengthwoodlandCritters[3]
failed to prove index is valid, possible solutions:
  - Use `have`-expressions to prove the index is valid
  - Use `a[i]!` notation instead, runtime check is performed, and 'Panic' error message is produced if index is not valid
  - Use `a[i]?` notation instead, result is an `Option` type
  - Use `a[i]'h` notation instead, where `h` is a proof that index is valid
โŠข 3 < woodlandCritters.length

์ด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋Š” Lean์ด 3 < woodlandCritters.length(์ฆ‰ 3 < List.length woodlandCritters)์„ ์ž๋™์œผ๋กœ ์ˆ˜ํ•™์ ์œผ๋กœ ์ฆ๋ช…ํ•ด ์กฐํšŒ๊ฐ€ ์•ˆ์ „ํ•จ์„ ๋ณด์ด๋ ค ํ–ˆ์ง€๋งŒ ๊ทธ๋ ‡๊ฒŒ ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค๋Š” ๋œป์ด๋‹ค. ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” ์˜ค๋ฅ˜๋Š” ํ”ํ•œ ๋ฒ„๊ทธ ์œ ํ˜•์ด๋ฉฐ, Lean์€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด์ž ์ •๋ฆฌ ์ฆ๋ช…๊ธฐ๋ผ๋Š” ์ด์ค‘์ ์ธ ์„ฑ๊ฒฉ์„ ํ™œ์šฉํ•ด ๊ฐ€๋Šฅํ•œ ํ•œ ๋งŽ์€ ์˜ค๋ฅ˜๋ฅผ ๋ฐฐ์ œํ•œ๋‹ค.

์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๋ ค๋ฉด ๋ช…์ œ, ์ฆ๋ช…, ์ „์ˆ ์ด๋ผ๋Š” ์„ธ ๊ฐ€์ง€ ํ•ต์‹ฌ ์•„์ด๋””์–ด๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•œ๋‹ค.

Propositions and Proofs๐Ÿ”—

๋ช…์ œ๋Š” ์ฐธ์ด๊ฑฐ๋‚˜ ๊ฑฐ์ง“์ผ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์žฅ์ด๋‹ค. ๋‹ค์Œ ์˜์–ด ๋ฌธ์žฅ์€ ๋ชจ๋‘ ๋ช…์ œ๋‹ค.

  • 1 + 1 = 2

  • ๋ง์…ˆ์€ ๊ตํ™˜๋ฒ•์น™์„ ๋งŒ์กฑํ•œ๋‹ค.

  • ์†Œ์ˆ˜๋Š” ๋ฌดํ•œํžˆ ๋งŽ๋‹ค.

  • 1 + 1 = 15

  • ํŒŒ๋ฆฌ๋Š” ํ”„๋ž‘์Šค์˜ ์ˆ˜๋„๋‹ค.

  • ๋ถ€์—๋…ธ์Šค์•„์ด๋ ˆ์Šค๋Š” ๋Œ€ํ•œ๋ฏผ๊ตญ์˜ ์ˆ˜๋„๋‹ค.

  • ๋ชจ๋“  ์ƒˆ๋Š” ๋‚  ์ˆ˜ ์žˆ๋‹ค.

๋ฐ˜๋ฉด์— ๋ฌด์˜๋ฏธํ•œ ๋ฌธ์žฅ์€ ๋ช…์ œ๊ฐ€ ์•„๋‹ˆ๋‹ค. ๋ฌธ๋ฒ•์ ์œผ๋กœ๋Š” ๋งž๋”๋ผ๋„ ๋‹ค์Œ ๋ฌธ์žฅ์€ ์–ด๋А ๊ฒƒ๋„ ๋ช…์ œ๊ฐ€ ์•„๋‹ˆ๋‹ค.

  • 1 + green = ice cream

  • ๋ชจ๋“  ์ˆ˜๋„๋Š” ์†Œ์ˆ˜๋‹ค.

  • ์ ์–ด๋„ ํ•˜๋‚˜์˜ gorg๋Š” fleep์ด๋‹ค.

๋ช…์ œ์—๋Š” ๋‘ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค. ๊ฐœ๋…์˜ ์ •์˜์—๋งŒ ์˜์กดํ•˜๋Š” ์ˆœ์ˆ˜ํ•œ ์ˆ˜ํ•™์  ๋ช…์ œ์™€ ์„ธ๊ณ„์— ๊ด€ํ•œ ์‚ฌ์‹ค์ด๋‹ค. Lean ๊ฐ™์€ ์ •๋ฆฌ ์ฆ๋ช…๊ธฐ๋Š” ์ „์ž์— ๊ด€์‹ฌ์ด ์žˆ์œผ๋ฉฐ, ํŽญ๊ท„์ด ๋‚  ์ˆ˜ ์žˆ๋Š”์ง€๋‚˜ ๋„์‹œ์˜ ๋ฒ•์  ์ง€์œ„์— ๋Œ€ํ•ด์„œ๋Š” ๋งํ•  ์ˆ˜ ์—†๋‹ค.

์ฆ๋ช…์€ ๋ช…์ œ๊ฐ€ ์ฐธ์ด๋ผ๋Š” ์„ค๋“๋ ฅ ์žˆ๋Š” ๋…ผ์ฆ์ด๋‹ค. ์ˆ˜ํ•™์  ๋ช…์ œ์˜ ๋…ผ์ฆ์€ ๊ด€๋ จ๋œ ๊ฐœ๋…์˜ ์ •์˜์™€ ๋…ผ๋ฆฌ์  ์ถ”๋ก  ๊ทœ์น™์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์ฆ๋ช…์€ ์‚ฌ๋žŒ์ด ์ดํ•ดํ•˜๋„๋ก ์ž‘์„ฑํ•˜๋ฏ€๋กœ ์ง€๋ฃจํ•œ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ๋งŽ์ด ์ƒ๋žตํ•œ๋‹ค. Lean ๊ฐ™์€ ์ปดํ“จํ„ฐ ๋ณด์กฐ ์ •๋ฆฌ ์ฆ๋ช…๊ธฐ๋Š” ์ˆ˜ํ•™์ž๊ฐ€ ๋งŽ์€ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์ƒ๋žตํ•˜๊ณ  ์ฆ๋ช…์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉฐ, ๋น ์ง„ ๋ช…์‹œ์  ๋‹จ๊ณ„๋ฅผ ์ฑ„์šฐ๋Š” ๊ฒƒ์€ ์†Œํ”„ํŠธ์›จ์–ด์˜ ์ฑ…์ž„์ด๋‹ค. ์ด ๋‹จ๊ณ„๋“ค์€ ๊ธฐ๊ณ„์ ์œผ๋กœ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ ๋น ๋œจ๋ฆผ์ด๋‚˜ ์‹ค์ˆ˜์˜ ๊ฐ€๋Šฅ์„ฑ์ด ์ค„์–ด๋“ ๋‹ค.

Lean์—์„œ ํ”„๋กœ๊ทธ๋žจ์˜ ํƒ€์ž…์€ ํ”„๋กœ๊ทธ๋žจ๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์„ ์„ค๋ช…ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Nat โ†’ List String ํƒ€์ž…์˜ ํ”„๋กœ๊ทธ๋žจ์€ Nat ์ธ์ˆ˜๋ฅผ ๋ฐ›์•„ ๋ฌธ์ž์—ด ๋ชฉ๋ก์„ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜๋‹ค. ๋‹ค์‹œ ๋งํ•ด ๊ฐ ํƒ€์ž…์€ ๊ทธ ํƒ€์ž…์„ ๊ฐ€์ง„ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ธ์ •๋˜๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์ง€์ •ํ•œ๋‹ค.

Lean์—์„œ ๋ช…์ œ๋Š” ์‚ฌ์‹ค ํƒ€์ž…์ด๋‹ค. ๋ช…์ œ๋Š” ๊ทธ ๋ฌธ์žฅ์ด ์ฐธ์ด๋ผ๋Š” ์ฆ๊ฑฐ๋กœ ์ธ์ •๋˜๋Š” ๊ฒƒ์„ ์ง€์ •ํ•œ๋‹ค. ์ด ์ฆ๊ฑฐ๋ฅผ ์ œ๊ณตํ•˜๋ฉด ๋ช…์ œ๊ฐ€ ์ฆ๋ช…๋˜๊ณ , Lean์ด ์ฆ๊ฑฐ๋ฅผ ๊ฒ€์‚ฌํ•œ๋‹ค. ๋ฐ˜๋ฉด ๋ช…์ œ๊ฐ€ ๊ฑฐ์ง“์ด๋ฉด ์ด ์ฆ๊ฑฐ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ช…์ œ 1 + 1 = 2๋Š” Lean์— ์ง์ ‘ ์“ธ ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ช…์ œ์˜ ์ฆ๊ฑฐ๋Š” ๋ฐ˜์‚ฌ์„ฑ(reflexivity)์˜ ์ค„์ž„๋ง์ธ rfl ์ƒ์„ฑ์ž๋‹ค. ์ˆ˜ํ•™์—์„œ ๋ชจ๋“  ์›์†Œ๊ฐ€ ์ž๊ธฐ ์ž์‹ ๊ณผ ๊ด€๊ณ„๋ฅผ ๋งบ์œผ๋ฉด ๊ด€๊ณ„๊ฐ€ ๋ฐ˜์‚ฌ์ ์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ด๋Š” ํƒ€๋‹นํ•œ ๋™๋“ฑ์„ฑ ๊ฐœ๋…์„ ๊ฐ–๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ์š”๊ตฌ ์‚ฌํ•ญ์ด๋‹ค. 1 + 1์€ 2๋กœ ๊ณ„์‚ฐ๋˜๋ฏ€๋กœ ์‹ค์ œ๋กœ ๊ฐ™์€ ๊ฒƒ์ด๋‹ค.

Definition `onePlusOneIsTwo` is a proposition; use `theorem` instead of `def` Note: This linter can be disabled with `set_option linter.defProp false`def onePlusOneIsTwo : 1 + 1 = 2 := rfl

๋ฐ˜๋ฉด rfl์€ ๊ฑฐ์ง“ ๋ช…์ œ 1 + 1 = 15๋ฅผ ์ฆ๋ช…ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

def Not a definitional equality: the left-hand side 1 + 1 is not definitionally equal to the right-hand side 15onePlusOneIsFifteen : 1 + 1 = 15 := Type mismatch rfl has type ?m.16 = ?m.16 but is expected to have type 1 + 1 = 15rfl
Type mismatch
  rfl
has type
  ?m.16 = ?m.16
but is expected to have type
  1 + 1 = 15

์ด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋Š” ๋™๋“ฑ์„ฑ ๋ฌธ์žฅ์˜ ์–‘๋ณ€์ด ์ด๋ฏธ ๊ฐ™์€ ์ˆ˜์ผ ๋•Œ rfl์ด ๋‘ ์‹์ด ๊ฐ™์Œ์„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค. 1 + 1์€ ๋ฐ”๋กœ 2๋กœ ํ‰๊ฐ€๋˜๋ฏ€๋กœ ๊ฐ™์€ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜๊ณ , ์ด์— ๋”ฐ๋ผ onePlusOneIsTwo๊ฐ€ ๋ฐ›์•„๋“ค์—ฌ์ง„๋‹ค. Type์ด ์ž๋ฃŒ๊ตฌ์กฐ์™€ ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” Nat, String, List (Nat ร— String ร— (Int โ†’ Float)) ๊ฐ™์€ ํƒ€์ž…์„ ์„ค๋ช…ํ•˜๋“ฏ, Prop์€ ๋ช…์ œ๋ฅผ ์„ค๋ช…ํ•œ๋‹ค.

๋ช…์ œ๊ฐ€ ์ฆ๋ช…๋˜๋ฉด ์ด๋ฅผ ์ •๋ฆฌ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. Lean์—์„œ๋Š” ์ •๋ฆฌ๋ฅผ def ๋Œ€์‹  theorem ํ‚ค์›Œ๋“œ๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์ด ๊ด€๋ก€๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋…์ž๊ฐ€ ์–ด๋–ค ์„ ์–ธ์„ ์ˆ˜ํ•™์  ์ฆ๋ช…์œผ๋กœ ์ฝ์–ด์•ผ ํ•˜๊ณ  ์–ด๋–ค ์„ ์–ธ์„ ์ •์˜๋กœ ์ฝ์–ด์•ผ ํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ฆ๋ช…์—์„œ๋Š” ๋ช…์ œ๊ฐ€ ์ฐธ์ด๋ผ๋Š” ์ฆ๊ฑฐ๊ฐ€ ์žˆ๋‹ค๋Š” ์ ์ด ์ค‘์š”ํ•˜๊ณ , ์–ด๋–ค ์ฆ๊ฑฐ๋ฅผ ์ œ๊ณตํ–ˆ๋Š”์ง€๋Š” ํŠน๋ณ„ํžˆ ์ค‘์š”ํ•˜์ง€ ์•Š๋‹ค. ๋ฐ˜๋ฉด ์ •์˜์—์„œ๋Š” ์–ด๋–ค ํŠน์ • ๊ฐ’์„ ์„ ํƒํ•˜๋Š”์ง€๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค. ํ•ญ์ƒ 0์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ง์…ˆ ์ •์˜๋Š” ๋ถ„๋ช…ํžˆ ์ž˜๋ชป๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ฆ๋ช…์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์€ ์ดํ›„ ์ฆ๋ช…์— ์ค‘์š”ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ theorem ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Lean ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋” ํฐ ๋ณ‘๋ ฌ์„ฑ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์•ž์˜ ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‹ค์‹œ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

def OnePlusOneIsTwo : Prop := 1 + 1 = 2 theorem onePlusOneIsTwo : OnePlusOneIsTwo := rfl

Tactics๐Ÿ”—

์ฆ๋ช…์€ ๋ณดํ†ต ์ฆ๊ฑฐ๋ฅผ ์ง์ ‘ ์ œ๊ณตํ•˜๊ธฐ๋ณด๋‹ค ์ „์ˆ ์„ ์‚ฌ์šฉํ•ด ์ž‘์„ฑํ•œ๋‹ค. ์ „์ˆ ์€ ๋ช…์ œ์˜ ์ฆ๊ฑฐ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์ž‘์€ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค. ์ด ํ”„๋กœ๊ทธ๋žจ์€ ์ฆ๋ช…ํ•  ๋ฌธ์žฅ(๋ชฉํ‘œ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค)๊ณผ ์ด๋ฅผ ์ฆ๋ช…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์ •์„ ์ถ”์ ํ•˜๋Š” ์ฆ๋ช… ์ƒํƒœ์—์„œ ์‹คํ–‰๋œ๋‹ค. ๋ชฉํ‘œ์— ์ „์ˆ ์„ ์‹คํ–‰ํ•˜๋ฉด ์ƒˆ๋กœ์šด ๋ชฉํ‘œ๊ฐ€ ๋“ค์–ด ์žˆ๋Š” ์ƒˆ ์ฆ๋ช… ์ƒํƒœ๊ฐ€ ๋‚˜์˜จ๋‹ค. ๋ชจ๋“  ๋ชฉํ‘œ๊ฐ€ ์ฆ๋ช…๋˜๋ฉด ์ฆ๋ช…์ด ์™„์„ฑ๋œ๋‹ค.

์ „์ˆ ๋กœ ์ฆ๋ช…์„ ์ž‘์„ฑํ•˜๋ ค๋ฉด ์ •์˜๋ฅผ by๋กœ ์‹œ์ž‘ํ•˜๋ผ. by๋ฅผ ์“ฐ๋ฉด Lean์€ ๋‹ค์Œ ๋“ค์—ฌ์“ฐ๊ธฐ ๋ธ”๋ก์ด ๋๋‚  ๋•Œ๊นŒ์ง€ ์ „์ˆ  ๋ชจ๋“œ๋กœ ๋“ค์–ด๊ฐ„๋‹ค. ์ „์ˆ  ๋ชจ๋“œ์—์„œ Lean์€ ํ˜„์žฌ ์ฆ๋ช… ์ƒํƒœ์— ๊ด€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๊ณ„์† ์ œ๊ณตํ•œ๋‹ค. ์ „์ˆ ๋กœ ์ž‘์„ฑํ•œ onePlusOneIsTwo๋Š” ์—ฌ์ „ํžˆ ๋งค์šฐ ์งง๋‹ค.

theorem onePlusOneIsTwo : 1 + 1 = 2 := โŠข 1 + 1 = 2 All goals completed! ๐Ÿ™

decide ์ „์ˆ ์€ ๋ฌธ์žฅ์ด ์ฐธ์ธ์ง€ ๊ฑฐ์ง“์ธ์ง€ ๊ฒ€์‚ฌํ•˜๊ณ  ์–ด๋А ๊ฒฝ์šฐ๋“  ์ ์ ˆํ•œ ์ฆ๋ช…์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ธ ๊ฒฐ์ • ์ ˆ์ฐจ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ์ฃผ๋กœ 1, 2 ๊ฐ™์€ ๊ตฌ์ฒด์ ์ธ ๊ฐ’์„ ๋‹ค๋ฃฐ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์ด ์ฑ…์˜ ๋‹ค๋ฅธ ์ค‘์š”ํ•œ ์ „์ˆ ์€ โ€œ๋‹จ์ˆœํ™”โ€๋ฅผ ๋œปํ•˜๋Š” simp์™€ ๋งŽ์€ ์ •๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” grind๋‹ค.

์ „์ˆ ์€ ์—ฌ๋Ÿฌ ์ด์œ ๋กœ ์œ ์šฉํ•˜๋‹ค.

  1. ๋งŽ์€ ์ฆ๋ช…์€ ๊ฐ€์žฅ ์ž‘์€ ์„ธ๋ถ€ ์‚ฌํ•ญ๊นŒ์ง€ ์ง์ ‘ ์“ฐ๋ฉด ๋ณต์žกํ•˜๊ณ  ์ง€๋ฃจํ•˜์ง€๋งŒ, ์ „์ˆ ์€ ์ด๋Ÿฐ ํฅ๋ฏธ๋กญ์ง€ ์•Š์€ ๋ถ€๋ถ„์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

  2. ์œ ์—ฐํ•œ ์ž๋™ํ™”๊ฐ€ ์ •์˜์˜ ์ž‘์€ ๋ณ€๊ฒฝ์„ ๊ฐ€๋ ค ์ค„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ „์ˆ ๋กœ ์ž‘์„ฑํ•œ ์ฆ๋ช…์€ ์‹œ๊ฐ„์ด ์ง€๋‚˜๋„ ์œ ์ง€ํ•˜๊ธฐ ์‰ฝ๋‹ค.

  3. ํ•˜๋‚˜์˜ ์ „์ˆ ๋กœ ์—ฌ๋Ÿฌ ์ •๋ฆฌ๋ฅผ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Lean์€ ๋‚ด๋ถ€์ ์œผ๋กœ ์ „์ˆ ์„ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์†์œผ๋กœ ์ฆ๋ช…์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋˜๊ฒŒ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐฐ์—ด ์กฐํšŒ์—๋Š” ์ธ๋ฑ์Šค๊ฐ€ ๋ฒ”์œ„ ์•ˆ์— ์žˆ๋‹ค๋Š” ์ฆ๋ช…์ด ํ•„์š”ํ•˜์ง€๋งŒ, ์ „์ˆ ์€ ๋ณดํ†ต ์‚ฌ์šฉ์ž๊ฐ€ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์•„๋„ ๊ทธ ์ฆ๋ช…์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‚ด๋ถ€์ ์œผ๋กœ ์ธ๋ฑ์‹ฑ ํ‘œ๊ธฐ๋ฒ•์€ ์ „์ˆ ์„ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž์˜ ์กฐํšŒ ์—ฐ์‚ฐ์ด ์•ˆ์ „ํ•จ์„ ์ฆ๋ช…ํ•œ๋‹ค. ์ด ์ „์ˆ ์€ ์‚ฐ์ˆ ์— ๊ด€ํ•œ ๋งŽ์€ ์‚ฌ์‹ค์„ ๊ณ ๋ คํ•˜๊ณ  ํ˜„์žฌ ๋ฒ”์œ„์—์„œ ์•Œ๋ ค์ง„ ์‚ฌ์‹ค๊ณผ ๊ฒฐํ•ฉํ•ด ์ธ๋ฑ์Šค๊ฐ€ ๋ฒ”์œ„ ์•ˆ์— ์žˆ์Œ์„ ์ฆ๋ช…ํ•˜๋ ค ํ•œ๋‹ค.

simp ์ „์ˆ ์€ Lean ์ฆ๋ช…์˜ ์ผ๊พผ์ด๋‹ค. ๋ชฉํ‘œ๋ฅผ ๊ฐ€๋Šฅํ•œ ํ•œ ๋‹จ์ˆœํ•œ ํ˜•ํƒœ๋กœ ๋‹ค์‹œ ์“ด๋‹ค. ๋งŽ์€ ๊ฒฝ์šฐ ์ด๋ ‡๊ฒŒ ๋‹ค์‹œ ์“ฐ๋ฉด ๋ฌธ์žฅ์ด ์ถฉ๋ถ„ํžˆ ๋‹จ์ˆœํ•ด์ ธ ์ž๋™์œผ๋กœ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” ์ž์„ธํ•œ ํ˜•์‹ ์ฆ๋ช…์ด ๊ตฌ์„ฑ๋˜์ง€๋งŒ simp๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๋ณต์žก์„ฑ์ด ๊ฐ€๋ ค์ง„๋‹ค.

decide์ฒ˜๋Ÿผ grind ์ „์ˆ ์€ ์ฆ๋ช…์„ ๋งˆ๋ฌด๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•œ๋‹ค. ๋‹ค์–‘ํ•œ ์ •๋ฆฌ๋ฅผ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” SMT ์†”๋ฒ„์˜ ๊ธฐ๋ฒ• ๋ชจ์Œ์„ ์‚ฌ์šฉํ•œ๋‹ค. simp์™€ ๋‹ฌ๋ฆฌ grind๋Š” ์ฆ๋ช…์„ ์™„์ „ํžˆ ๋๋‚ด์ง€ ์•Š๊ณ ๋Š” ์ฆ๋ช…์„ ํ–ฅํ•ด ์กฐ๊ธˆ๋„ ๋‚˜์•„๊ฐˆ ์ˆ˜ ์—†์œผ๋ฉฐ, ์™„์ „ํžˆ ์„ฑ๊ณตํ•˜๊ฑฐ๋‚˜ ์‹คํŒจํ•œ๋‹ค. grind ์ „์ˆ ์€ ๋งค์šฐ ๊ฐ•๋ ฅํ•˜๊ณ  ์‚ฌ์šฉ์žํ™”ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๋‹ค. ์ด ํž˜๊ณผ ์œ ์—ฐ์„ฑ ๋•Œ๋ฌธ์— ์ •๋ฆฌ๋ฅผ ์ฆ๋ช…ํ•˜์ง€ ๋ชปํ–ˆ์„ ๋•Œ์˜ ์ถœ๋ ฅ์—๋Š” ์ˆ™๋ จ๋œ Lean ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํŒจ ์ด์œ ๋ฅผ ์ง„๋‹จํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์ •๋ณด๊ฐ€ ๋งŽ์ด ๋‹ด๊ธด๋‹ค. ์ด๋Š” ์ฒ˜์Œ์—๋Š” ๋ฒ…์ฐฐ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ด ์žฅ์—์„œ๋Š” decide์™€ simp๋งŒ ์‚ฌ์šฉํ•œ๋‹ค.

Connectives๐Ÿ”—

โ€œ๊ทธ๋ฆฌ๊ณ โ€, โ€œ๋˜๋Š”โ€, โ€œ์ฐธโ€, โ€œ๊ฑฐ์ง“โ€, โ€œ์•„๋‹ˆ๋‹คโ€์™€ ๊ฐ™์€ ๋…ผ๋ฆฌ์˜ ๊ธฐ๋ณธ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋…ผ๋ฆฌ ์—ฐ๊ฒฐ์‚ฌ๋ผ๊ณ  ํ•œ๋‹ค. ๊ฐ ์—ฐ๊ฒฐ์‚ฌ๋Š” ๊ทธ ์—ฐ๊ฒฐ์‚ฌ๊ฐ€ ์ฐธ์ด๋ผ๋Š” ์ฆ๊ฑฐ๋กœ ์ธ์ •๋˜๋Š” ๊ฒƒ์„ ์ •์˜ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด โ€œA ๊ทธ๋ฆฌ๊ณ  Bโ€๋ผ๋Š” ๋ฌธ์žฅ์„ ์ฆ๋ช…ํ•˜๋ ค๋ฉด A์™€ B๋ฅผ ๋ชจ๋‘ ์ฆ๋ช…ํ•ด์•ผ ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ โ€œA ๊ทธ๋ฆฌ๊ณ  Bโ€์˜ ์ฆ๊ฑฐ๋Š” A์˜ ์ฆ๊ฑฐ์™€ B์˜ ์ฆ๊ฑฐ๋ฅผ ๋ชจ๋‘ ๋‹ด์€ ์Œ์ด๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ โ€œA ๋˜๋Š” Bโ€์˜ ์ฆ๊ฑฐ๋Š” A์˜ ์ฆ๊ฑฐ๋‚˜ B์˜ ์ฆ๊ฑฐ ์ค‘ ํ•˜๋‚˜๋‹ค.

ํŠนํžˆ ์ด๋Ÿฌํ•œ ์—ฐ๊ฒฐ์‚ฌ ๋Œ€๋ถ€๋ถ„์€ ๋ฐ์ดํ„ฐ ํƒ€์ž…์ฒ˜๋Ÿผ ์ •์˜๋˜๋ฉฐ ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€์ง„๋‹ค. A์™€ B๊ฐ€ ๋ช…์ œ๋ผ๋ฉด โ€œA ๊ทธ๋ฆฌ๊ณ  Bโ€(ํ‘œ๊ธฐ๋Š” A โˆง B)๋„ ๋ช…์ œ๋‹ค. A โˆง B์˜ ์ฆ๊ฑฐ๋Š” A โ†’ B โ†’ A โˆง B ํƒ€์ž…์„ ๊ฐ–๋Š” And.intro ์ƒ์„ฑ์ž๋‹ค. A์™€ B๋ฅผ ๊ตฌ์ฒด์ ์ธ ๋ช…์ œ๋กœ ๋ฐ”๊พธ๋ฉด And.intro rfl rfl๋กœ 1 + 1 = 2 โˆง "Str".append "ing" = "String"์„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก  decide๋„ ์ด ์ฆ๋ช…์„ ์ฐพ์„ ๋งŒํผ ๊ฐ•๋ ฅํ•˜๋‹ค.

theorem addAndAppend : 1 + 1 = 2 โˆง "Str".append "ing" = "String" := โŠข 1 + 1 = 2 โˆง "Str".append "ing" = "String" All goals completed! ๐Ÿ™

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ โ€œA ๋˜๋Š” Bโ€(ํ‘œ๊ธฐ๋Š” A โˆจ B)์—๋Š” ๋‘ ์ƒ์„ฑ์ž๊ฐ€ ์žˆ๋‹ค. โ€œA ๋˜๋Š” Bโ€์˜ ์ฆ๋ช…์—๋Š” ๋‘ ๋ช…์ œ ์ค‘ ํ•˜๋‚˜๋งŒ ์ฐธ์ด๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋‘ ์ƒ์„ฑ์ž๋Š” A โ†’ A โˆจ B ํƒ€์ž…์˜ Or.inl๊ณผ B โ†’ A โˆจ B ํƒ€์ž…์˜ Or.inr๋‹ค.

ํ•จ์ˆ˜๋Š” ํ•จ์˜(A์ด๋ฉด B)๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ํŠนํžˆ A์˜ ์ฆ๊ฑฐ๋ฅผ B์˜ ์ฆ๊ฑฐ๋กœ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜ ์ž์ฒด๊ฐ€ A๊ฐ€ B๋ฅผ ํ•จ์˜ํ•œ๋‹ค๋Š” ์ฆ๊ฑฐ๋‹ค. ์ด๋Š” A โ†’ B๋ฅผ ยฌA โˆจ B์˜ ์ค„์ž„๋ง๋กœ ๋ณด๋Š” ์ผ๋ฐ˜์ ์ธ ์„ค๋ช…๊ณผ ๋‹ค๋ฅด์ง€๋งŒ ๋‘ ํ‘œํ˜„์€ ๋™๋“ฑํ•˜๋‹ค.

โ€œ๊ทธ๋ฆฌ๊ณ โ€์˜ ์ฆ๊ฑฐ๋Š” ์ƒ์„ฑ์ž์ด๋ฏ€๋กœ ํŒจํ„ด ๋งค์นญ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด A ๊ทธ๋ฆฌ๊ณ  B๊ฐ€ A ๋˜๋Š” B๋ฅผ ํ•จ์˜ํ•œ๋‹ค๋Š” ์ฆ๋ช…์€, A ๊ทธ๋ฆฌ๊ณ  B์˜ ์ฆ๊ฑฐ์—์„œ A์˜ ์ฆ๊ฑฐ(๋˜๋Š” B์˜ ์ฆ๊ฑฐ)๋ฅผ ๊บผ๋‚ด ๊ทธ ์ฆ๊ฑฐ๋กœ A ๋˜๋Š” B์˜ ์ฆ๊ฑฐ๋ฅผ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜๋‹ค.

theorem andImpliesOr : A โˆง B โ†’ A โˆจ B := fun andEvidence => match andEvidence with | And.intro a b => Or.inl a

์—ฐ๊ฒฐ์‚ฌ

Lean ๋ฌธ๋ฒ•

์ฆ๊ฑฐ

์ฐธ

True

True.intro : True

๊ฑฐ์ง“

False

์ฆ๊ฑฐ ์—†์Œ

A์ด๊ณ  B

A โˆง B

And.intro : A โ†’ B โ†’ A โˆง B

A ๋˜๋Š” B

A โˆจ B

Or.inl : A โ†’ A โˆจ B ๋˜๋Š” Or.inr : B โ†’ A โˆจ B ์ค‘ ํ•˜๋‚˜

A์ด๋ฉด B

A โ†’ B

A์˜ ์ฆ๊ฑฐ๋ฅผ B์˜ ์ฆ๊ฑฐ๋กœ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜

A๊ฐ€ ์•„๋‹˜

ยฌA

A์˜ ์ฆ๊ฑฐ๋ฅผ False์˜ ์ฆ๊ฑฐ๋กœ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜

decide ์ „์ˆ ์€ ์ด๋Ÿฌํ•œ ์—ฐ๊ฒฐ์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ •๋ฆฌ๋ฅผ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

theorem onePlusOneOrLessThan : 1 + 1 = 2 โˆจ 3 < 5 := โŠข 1 + 1 = 2 โˆจ 3 < 5 All goals completed! ๐Ÿ™ theorem notTwoEqualFive : ยฌ(1 + 1 = 5) := โŠข ยฌ1 + 1 = 5 All goals completed! ๐Ÿ™ theorem trueIsTrue : True := โŠข True All goals completed! ๐Ÿ™ theorem trueOrFalse : True โˆจ False := โŠข True โˆจ False All goals completed! ๐Ÿ™ theorem falseImpliesTrue : False โ†’ True := โŠข False โ†’ True All goals completed! ๐Ÿ™

Evidence as Arguments๐Ÿ”—

์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๋ชฉ๋ก์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ธ๋ฑ์‹ฑํ•˜๋ ค๋ฉด ๋ชฉ๋ก์— ์ตœ์†Œ ํฌ๊ธฐ๊ฐ€ ์žˆ์–ด์•ผ ํ•˜์ง€๋งŒ ๋ชฉ๋ก ์ž์ฒด๋Š” ๊ตฌ์ฒด์ ์ธ ๊ฐ’์ด ์•„๋‹ˆ๋ผ ๋ณ€์ˆ˜๋‹ค. ์ด ์กฐํšŒ๊ฐ€ ์•ˆ์ „ํ•˜๋ ค๋ฉด ๋ชฉ๋ก์ด ์ถฉ๋ถ„ํžˆ ๊ธธ๋‹ค๋Š” ์ฆ๊ฑฐ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์ธ๋ฑ์‹ฑ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ์•ˆ์ „์„ฑ์— ํ•„์š”ํ•œ ์ฆ๊ฑฐ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ชฉ๋ก์˜ ์„ธ ๋ฒˆ์งธ ํ•ญ๋ชฉ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋Š” ๋ชฉ๋ก์— ์›์†Œ๊ฐ€ 0๊ฐœ, 1๊ฐœ, 2๊ฐœ์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ผ๋ฐ˜์ ์œผ๋กœ ์•ˆ์ „ํ•˜์ง€ ์•Š๋‹ค.

def third (xs : List ฮฑ) : ฮฑ := failed to prove index is valid, possible solutions: - Use `have`-expressions to prove the index is valid - Use `a[i]!` notation instead, runtime check is performed, and 'Panic' error message is produced if index is not valid - Use `a[i]?` notation instead, result is an `Option` type - Use `a[i]'h` notation instead, where `h` is a proof that index is valid ฮฑ:Type ?u.3xs:List ฮฑโŠข 2 < xs.lengthxs[2]
failed to prove index is valid, possible solutions:
  - Use `have`-expressions to prove the index is valid
  - Use `a[i]!` notation instead, runtime check is performed, and 'Panic' error message is produced if index is not valid
  - Use `a[i]?` notation instead, result is an `Option` type
  - Use `a[i]'h` notation instead, where `h` is a proof that index is valid
ฮฑ:Type ?u.3xs:List ฮฑโŠข 2 < xs.length

ํ•˜์ง€๋งŒ ์ธ๋ฑ์‹ฑ ์—ฐ์‚ฐ์ด ์•ˆ์ „ํ•˜๋‹ค๋Š” ์ฆ๊ฑฐ๋กœ ์ด๋ฃจ์–ด์ง„ ์ธ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ชฉ๋ก์— ํ•ญ๋ชฉ์ด ์ ์–ด๋„ ์„ธ ๊ฐœ ์žˆ์Œ์„ ๋ณด์ด๋Š” ์˜๋ฌด๋ฅผ ํ˜ธ์ถœ์ž์—๊ฒŒ ๋ถ€๊ณผํ•  ์ˆ˜ ์žˆ๋‹ค.

def third (xs : List ฮฑ) (ok : xs.length > 2) : ฮฑ := xs[2]

์ด ์˜ˆ์ œ์—์„œ xs.length > 2๋Š” xs์— ํ•ญ๋ชฉ์ด 2๊ฐœ๋ณด๋‹ค ๋งŽ์€์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์•„๋‹ˆ๋‹ค. ์ฐธ์ผ ์ˆ˜๋„ ๊ฑฐ์ง“์ผ ์ˆ˜๋„ ์žˆ๋Š” ๋ช…์ œ์ด๋ฉฐ, ok ์ธ์ˆ˜๋Š” ์ด ๋ช…์ œ๊ฐ€ ์ฐธ์ด๋ผ๋Š” ์ฆ๊ฑฐ์—ฌ์•ผ ํ•œ๋‹ค.

ํ•จ์ˆ˜๋ฅผ ๊ตฌ์ฒด์ ์ธ ๋ชฉ๋ก์— ํ˜ธ์ถœํ•˜๋ฉด ๋ชฉ๋ก์˜ ๊ธธ์ด๋ฅผ ์•ˆ๋‹ค. ์ด ๊ฒฝ์šฐ by decide๊ฐ€ ์ฆ๊ฑฐ๋ฅผ ์ž๋™์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

"snail"#eval third woodlandCritters (โŠข woodlandCritters.length > 2 All goals completed! ๐Ÿ™)
"snail"

Indexing Without Evidence๐Ÿ”—

์ธ๋ฑ์‹ฑ ์—ฐ์‚ฐ์ด ๋ฒ”์œ„ ์•ˆ์— ์žˆ์Œ์„ ์ฆ๋ช…ํ•˜๊ธฐ๊ฐ€ ํ˜„์‹ค์ ์ด์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค. ๋ฌผ์Œํ‘œ๋ฅผ ๋ถ™์ด๋ฉด Option์ด ๋˜๋ฉฐ, ์ธ๋ฑ์Šค๊ฐ€ ๋ฒ”์œ„ ์•ˆ์ด๋ฉด ๊ฒฐ๊ณผ๋Š” some์ด๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด none์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

def thirdOption (xs : List ฮฑ) : Option ฮฑ := xs[2]?some "snail"#eval thirdOption woodlandCritters
some "snail"
none#eval thirdOption ["only", "two"]
none

Option์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋Œ€์‹  ์ธ๋ฑ์Šค๊ฐ€ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์„ ์ค‘๋‹จํ•˜๋Š” ๋ฒ„์ „๋„ ์žˆ๋‹ค.

"deer"#eval woodlandCritters[1]!
"deer"

Messages You May Meet๐Ÿ”—

decide ์ „์ˆ ์€ ๋ฌธ์žฅ์ด ์ฐธ์ž„์„ ์ฆ๋ช…ํ•  ๋ฟ ์•„๋‹ˆ๋ผ ๊ฑฐ์ง“์ž„๋„ ์ฆ๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค. ์›์†Œ๊ฐ€ ํ•˜๋‚˜์ธ ๋ชฉ๋ก์— ์›์†Œ๊ฐ€ ๋‘ ๊ฐœ๋ณด๋‹ค ๋งŽ๋‹ค๊ณ  ์ฆ๋ช…ํ•˜๋ผ๊ณ  ํ•˜๋ฉด, ๋ฌธ์žฅ์ด ์‹ค์ œ๋กœ ๊ฑฐ์ง“์ž„์„ ๋‚˜ํƒ€๋‚ด๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

#eval third ["rabbit"] (โŠข ["rabbit"].length > 2 Tactic `decide` proved that the proposition ["rabbit"].length > 2 is falseโŠข ["rabbit"].length > 2)
Tactic `decide` proved that the proposition
  ["rabbit"].length > 2
is false

simp์™€ decide ์ „์ˆ ์€ def๋กœ ์ •์˜ํ•œ ๊ฒƒ์„ ์ž๋™์œผ๋กœ ํŽผ์น˜์ง€ ์•Š๋Š”๋‹ค. simp๋ฅผ ์‚ฌ์šฉํ•ด OnePlusOneIsTwo๋ฅผ ์ฆ๋ช…ํ•˜๋ ค ํ•˜๋ฉด ์‹คํŒจํ•œ๋‹ค.

theorem onePlusOneIsStillTwo : OnePlusOneIsTwo := โŠข OnePlusOneIsTwo `simp` made no progressโŠข OnePlusOneIsTwo

์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋Š” OnePlusOneIsTwo๋ฅผ ํŽผ์น˜์ง€ ์•Š์œผ๋ฉด ์ง„์ „ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ๋‹จ์ˆœํžˆ ๋งํ•œ๋‹ค.

`simp` made no progress

decide๋ฅผ ์‚ฌ์šฉํ•ด๋„ ์‹คํŒจํ•œ๋‹ค.

theorem onePlusOneIsStillTwo : OnePlusOneIsTwo := โŠข OnePlusOneIsTwo failed to synthesize Decidable OnePlusOneIsTwo Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command.โŠข OnePlusOneIsTwo

์ด ์—ญ์‹œ OnePlusOneIsTwo๋ฅผ ํŽผ์น˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

failed to synthesize
  Decidable OnePlusOneIsTwo

Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command.

abbrev๋กœ OnePlusOneIsTwo๋ฅผ ์ •์˜ํ•˜๋ฉด ํŽผ์น  ์ •์˜๋กœ ํ‘œ์‹œ๋˜๋ฏ€๋กœ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ๋‹ค.

์ธ๋ฑ์‹ฑ ์—ฐ์‚ฐ์ด ์•ˆ์ „ํ•˜๋‹ค๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„ ์ฆ๊ฑฐ๋ฅผ Lean์ด ์ฐพ์ง€ ๋ชปํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜ ์™ธ์—๋„, ์•ˆ์ „ํ•˜์ง€ ์•Š์€ ์ธ๋ฑ์‹ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๋‹คํ˜• ํ•จ์ˆ˜๋Š” ๋‹ค์Œ ๋ฉ”์‹œ์ง€๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

def unsafeThird (xs : List ฮฑ) : ฮฑ := failed to synthesize instance of type class Inhabited ฮฑ Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.xs[2]!
failed to synthesize instance of type class
  Inhabited ฮฑ

Hint: Type class instance resolution failures can be inspected with the `set_option trace.Meta.synthInstance true` command.

์ด๋Š” Lean์„ ์ •๋ฆฌ ์ฆ๋ช…์„ ์œ„ํ•œ ๋…ผ๋ฆฌ์ด์ž ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ธฐ์ˆ ์  ์ œํ•œ ๋•Œ๋ฌธ์ด๋‹ค. ํŠนํžˆ ํƒ€์ž…์— ๊ฐ’์ด ์ ์–ด๋„ ํ•˜๋‚˜ ํฌํ•จ๋œ ํ”„๋กœ๊ทธ๋žจ๋งŒ ์ค‘๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค. Lean์˜ ๋ช…์ œ๋Š” ์ฐธ์˜ ์ฆ๊ฑฐ๋ฅผ ๋ถ„๋ฅ˜ํ•˜๋Š” ์ผ์ข…์˜ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ฑฐ์ง“ ๋ช…์ œ์—๋Š” ๊ทธ๋Ÿฐ ์ฆ๊ฑฐ๊ฐ€ ์—†๋‹ค. ๋นˆ ํƒ€์ž…์„ ๊ฐ€์ง„ ํ”„๋กœ๊ทธ๋žจ์ด ์ค‘๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ทธ ์ค‘๋‹จํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๊ฑฐ์ง“ ๋ช…์ œ์˜ ๊ฐ€์งœ ์ฆ๊ฑฐ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‚ด๋ถ€์ ์œผ๋กœ Lean์—๋Š” ๊ฐ’์ด ์ ์–ด๋„ ํ•˜๋‚˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด ์•Œ๋ ค์ง„ ํƒ€์ž…์˜ ํ‘œ๊ฐ€ ์žˆ๋‹ค. ์ด ์˜ค๋ฅ˜๋Š” ์ž„์˜์˜ ํƒ€์ž… ฮฑ๊ฐ€ ๊ทธ ํ‘œ์— ๋ฐ˜๋“œ์‹œ ๋“ค์–ด ์žˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๋œป์ด๋‹ค. ๋‹ค์Œ ์žฅ์—์„œ๋Š” ์ด ํ‘œ์— ํƒ€์ž…์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ unsafeThird ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค.

๋ชฉ๋ก๊ณผ ์กฐํšŒ์— ์‚ฌ์šฉํ•˜๋Š” ๋Œ€๊ด„ํ˜ธ ์‚ฌ์ด์— ๊ณต๋ฐฑ์„ ๋„ฃ์œผ๋ฉด ๋˜ ๋‹ค๋ฅธ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

#eval Function expected at woodlandCritters but this term has type List String Note: Expected a function because this term is being applied to the argument [1]woodlandCritters [1]
Function expected at
  woodlandCritters
but this term has type
  List String

Note: Expected a function because this term is being applied to the argument
  [1]

๊ณต๋ฐฑ์„ ๋„ฃ์œผ๋ฉด Lean์€ ์‹์„ ํ•จ์ˆ˜ ์ ์šฉ์œผ๋กœ, ์ธ๋ฑ์Šค๋ฅผ ์ˆซ์ž ํ•˜๋‚˜๋ฅผ ๋‹ด์€ ๋ชฉ๋ก์œผ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค. ์ด ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋Š” Lean์ด woodlandCritters๋ฅผ ํ•จ์ˆ˜๋กœ ์ทจ๊ธ‰ํ•˜๋ ค ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜์˜จ๋‹ค.

Exercises๐Ÿ”—

  • ๋‹ค์Œ ์ •๋ฆฌ๋ฅผ rfl๋กœ ์ฆ๋ช…ํ•˜๋ผ: 2 + 3 = 5, 15 - 8 = 7, "Hello, ".append "world" = "Hello, world". rfl๋กœ 5 < 18์„ ์ฆ๋ช…ํ•˜๋ ค ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋Š”๊ฐ€? ๊ทธ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•˜๋ผ.

  • ๋‹ค์Œ ์ •๋ฆฌ๋ฅผ by decide๋กœ ์ฆ๋ช…ํ•˜๋ผ: 2 + 3 = 5, 15 - 8 = 7, "Hello, ".append "world" = "Hello, world", 5 < 18.

  • ๋ชฉ๋ก์˜ ๋‹ค์„ฏ ๋ฒˆ์งธ ํ•ญ๋ชฉ์„ ์กฐํšŒํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋ผ. ์ด ์กฐํšŒ๊ฐ€ ์•ˆ์ „ํ•˜๋‹ค๋Š” ์ฆ๊ฑฐ๋ฅผ ํ•จ์ˆ˜์˜ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜๋ผ.