Functional Programming in Lean ํ๊ตญ์ด ๋ฒ์ญ - 1. Lean ์์๋ณด๊ธฐ
Note
์ด ๊ธ์ Lean ๊ณต์ ๋ฌธ์์ ์๊ฐ๋ Functional Programming in Lean์ ์์ฑ์๊ฐ ์ฝ๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก Kagi Translate๋ฅผ ํตํด 1์ฐจ๋ก ๊ธฐ๊ณ ๋ฒ์ญ ํ ๋ณด์ํ ๊ธ์
๋๋ค.์๋ฌธ๊ณผ์ ์ฐจ์ด๊ฐ ์์ ์ ์์ผ๋ฉฐ ์ ์ ๋ด์ฉ์ ํญ์ ์๋ฌธ์ ํตํด ํ์ธ ๋ฐ๋๋๋ค.์๋ฌธ์ด Creative Commons Attribution 4.0 International License๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฐฐํฌ๋ ๊ฒ์ ์กด์คํ์ฌ ์ด ๊ธ ๋ํ CC BY 4.0 ํ์ ๋ฐฐํฌํฉ๋๋ค.
1. Lean ์์๋ณด๊ธฐ
์ ํต์ ์ผ๋ก ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ์ฝ์์ "Hello, world!"๋ฅผ ์ถ๋ ฅํ๋ ํ๋ก๊ทธ๋จ์ ์ปดํ์ผํ๊ณ ์คํํจ์ผ๋ก์จ ์๊ฐ๋๊ณค ํฉ๋๋ค. ์ด ๊ฐ๋จํ ํ๋ก๊ทธ๋จ์ ์ธ์ด ๋๊ตฌ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ค์น๋์๋์ง, ๊ทธ๋ฆฌ๊ณ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ปดํ์ผ๋ ์ฝ๋๋ฅผ ์คํํ ์ ์๋์ง๋ฅผ ํ์ธํด ์ค๋๋ค.
ํ์ง๋ง 1970๋
๋ ์ดํ๋ก ํ๋ก๊ทธ๋๋ฐ์ ๋ณํํด ์์ต๋๋ค. ์ค๋๋ ์ปดํ์ผ๋ฌ๋ ๋๊ฐ ํ
์คํธ ์๋ํฐ์ ํตํฉ๋์ด ์์ผ๋ฉฐ, ํ๋ก๊ทธ๋๋ฐ ํ๊ฒฝ์ ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ ๋์ ํผ๋๋ฐฑ์ ์ ๊ณตํฉ๋๋ค. Lean๋ ์์ธ๋ ์๋๋๋ค. Lean์ ์ธ์ด ์๋ฒ ํ๋กํ ์ฝ ์ ํ์ฅ ๋ฒ์ ์ ๊ตฌํํ์ฌ ํ
์คํธ ์๋ํฐ์ ํต์ ํ๊ณ ์ฌ์ฉ์๊ฐ ์
๋ ฅํ๋ ๋์ ํผ๋๋ฐฑ์ ์ ๊ณตํ ์ ์๋๋ก ํฉ๋๋ค.
Python, Haskell, JavaScript์ ๊ฐ์ด ๋ค์ํ ์ธ์ด๋ค์ ํํ์์ด๋ ๋ฌธ์ฅ์ ์
๋ ฅํ ์ ์๋ REPL, ์ฆ ๋ํํ ํฑ๋ ๋ฒจ์ด๋ ๋ธ๋ผ์ฐ์ ์ฝ์์ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ธ์ด๋ ์ฌ์ฉ์์ ์
๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํ์ฌ ํ์ํฉ๋๋ค. ๋ฐ๋ฉด Lean์ ์ด๋ฌํ ๊ธฐ๋ฅ๋ค์ ์๋ํฐ์์ ์ํธ์์ฉ์ ํตํฉํ์ฌ, ํ
์คํธ ์๋ํฐ๊ฐ ํ๋ก๊ทธ๋จ ํ
์คํธ ์์ฒด์ ํตํฉ๋ ํผ๋๋ฐฑ์ ํ์ํ๋๋ก ํ๋ ๋ช
๋ น์ด๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด ์ฅ์์๋ ์๋ํฐ์์ Lean๊ณผ ์ํธ์์ฉํ๋ ๋ฐฉ๋ฒ์ ์งง๊ฒ ์๊ฐํ๋ฉฐ, Hello, World! ์ฅ์์๋ ๋ช
๋ น์ค์์ ๋ฐฐ์น ๋ชจ๋๋ก Lean์ ์ฌ์ฉํ๋ ์ ํต์ ์ธ ๋ฐฉ๋ฒ์ ์ค๋ช
ํฉ๋๋ค.
์๋ํฐ์ Lean์ ๋์ ๋๊ณ ๊ฐ ์์ ๋ฅผ ์ง์ ์
๋ ฅํ๋ฉฐ ์ด ์ฑ
์ ์ฝ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ์์ ๋ค์ ์ง์ ๋ค๋ฃจ์ด ๋ณด๋ฉฐ ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง ํ์ธํด ๋ณด์ธ์!
1.1. ํํ์ ํ๊ฐํ๊ธฐ
Lean์ ๋ฐฐ์ฐ๋ ํ๋ก๊ทธ๋๋จธ๋ก์ ์ดํดํด์ผ ํ ๊ฐ์ฅ ์ค์ํ ๊ฒ์ ํ๊ฐ๊ฐ ์ด๋ป๊ฒ ์๋ํ๋์ง์
๋๋ค. ํ๊ฐ๋ ์ฐ์์์์ฒ๋ผ ํํ์์ ๊ฐ์ ์ฐพ๋ ๊ณผ์ ์
๋๋ค. ์๋ฅผ ๋ค์ด, 15โ615โ6์ ๊ฐ์ 99์ด๊ณ 2ร(3+1)2ร(3+1)์ ๊ฐ์ 88์
๋๋ค. ํ์์ ํํ์ ๊ฐ์ ์ฐพ๊ธฐ ์ํด, 3+13+1์ ๋จผ์ 44๋ก ๋์ฒด๋์ด 2ร42ร4๊ฐ ๋๊ณ , ์ด๋ ๋ค์ 88๋ก ์ค์ด๋ค ์ ์์ต๋๋ค. ๋๋๋ก ์ํ์ ํํ์์๋ ๋ณ์๊ฐ ํฌํจ๋ฉ๋๋ค. x+1x+1์ ๊ฐ์ xx์ ๊ฐ์ ์๊ธฐ ์ ๊น์ง๋ ๊ณ์ฐํ ์ ์์ต๋๋ค. Lean์์ ํ๋ก๊ทธ๋จ์ ๋ฌด์๋ณด๋ค๋ ํํ์์ด๋ฉฐ, ๊ณ์ฐ์ ๋ํด ์๊ฐํ๋ ์ฃผ๋ ๋ฐฉ์์ ํํ์์ ํ๊ฐํ์ฌ ๊ทธ ๊ฐ์ ์ฐพ๋ ๊ฒ์
๋๋ค.
๋๋ถ๋ถ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ ๋ช
๋ นํ์ผ๋ก, ํ๋ก๊ทธ๋จ์ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ๊ธฐ ์ํด ์ํ๋์ด์ผ ํ ์ผ๋ จ์ ๋ฌธ์ฅ๋ค๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ํ๋ก๊ทธ๋จ์ ๋ณ๊ฒฝ ๊ฐ๋ฅํ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ ์ ์์ผ๋ฏ๋ก, ๋ณ์๊ฐ ์ฐธ์กฐํ๋ ๊ฐ์ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณํ ์ ์์ต๋๋ค. ๋ณ๊ฒฝ ๊ฐ๋ฅํ ์ํ ์ธ์๋, ํ๋ก๊ทธ๋จ์ ํ์ผ ์ญ์ , ์ธ๋ถ ๋คํธ์ํฌ ์ฐ๊ฒฐ, ์์ธ ๋ฐ์ ๋๋ ์ฒ๋ฆฌ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ ์ฝ๊ธฐ์ ๊ฐ์ ๋ค๋ฅธ ๋ถ์์ฉ์ ๊ฐ์ง ์ ์์ต๋๋ค. "๋ถ์์ฉ"์ ๋ณธ์ง์ ์ผ๋ก ์ํ์ ํํ์์ ํ๊ฐํ๋ ๋ชจ๋ธ์ ๋ฐ๋ฅด์ง ์๋ ํ๋ก๊ทธ๋จ์์ ์ผ์ด๋ ์ ์๋ ์ผ๋ค์ ์ค๋ช
ํ๋ ํฌ๊ด์ ์ธ ์ฉ์ด์
๋๋ค.
ํ์ง๋ง Lean์์๋ ํ๋ก๊ทธ๋จ์ด ์ํ์ ํํ์๊ณผ ๋์ผํ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ์ผ๋จ ๊ฐ์ด ์ฃผ์ด์ง๋ฉด ๋ณ์๋ ์ฌํ ๋น๋ ์ ์์ต๋๋ค. ํํ์์ ํ๊ฐํ๋ ๊ฒ์ ๋ถ์์ฉ์ ๊ฐ์ง ์ ์์ต๋๋ค. ๋ ํํ์์ด ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ฉด, ํ๋๋ฅผ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๋์ฒดํด๋ ํ๋ก๊ทธ๋จ์ด ๋ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํ๊ฒ ํ์ง ์์ต๋๋ค. ์ด๊ฒ์ด Lean์ผ๋ก ์ฝ์์ Hello, world!๋ฅผ ์ถ๋ ฅํ๋ ํ๋ก๊ทธ๋จ์ ์์ฑํ ์ ์๋ค๋ ์๋ฏธ๋ ์๋์ง๋ง, ์
์ถ๋ ฅ์ ์ํํ๋ ๊ฒ์ Lean์ ์ฌ์ฉํ๋ ๊ฒฝํ์ ํต์ฌ์ ์ธ ๋ถ๋ถ์ ์๋๋๋ค. ๋ฐ๋ผ์ ์ด ์ฅ์์๋ Lean์ผ๋ก ํํ์์ ๋ํ์์ผ๋ก ํ๊ฐํ๋ ๋ฐฉ๋ฒ์ ์ด์ ์ ๋ง์ถ๊ณ , ๋ค์ ์ฅ์์๋ Hello, world! ํ๋ก๊ทธ๋จ์ ์์ฑ, ์ปดํ์ผ ๋ฐ ์คํํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช
ํฉ๋๋ค.
Lean์๊ฒ ํํ์์ ํ๊ฐํ๋๋ก ์์ฒญํ๋ ค๋ฉด, ํธ์ง๊ธฐ์์ ๊ทธ ์์ #eval์ ์์ฑํ๋ฉด ๊ฒฐ๊ณผ๊ฐ ๋ค์ ๋ณด๊ณ ๋ฉ๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ๊ฒฐ๊ณผ๋ #eval ์์ ์ปค์๋ ๋ง์ฐ์ค ํฌ์ธํฐ๋ฅผ ์ฌ๋ ค๋์ผ๋ฉด ์ฐพ์ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด,
#eval 1 + 2
๋ ๋ค์ ๊ฐ์ ์ฐ์ถํฉ๋๋ค.
3
Lean์ ์ฐ์ ์ฐ์ฐ์์ ๋ํ ์ผ๋ฐ์ ์ธ ์ฐ์ ์์ ๋ฐ ๊ฒฐํฉ์ฑ ๊ท์น์ ๋ฐ๋ฆ
๋๋ค. ์ฆ,
#eval 1 + 2 * 5
๋ 15๊ฐ ์๋ 11์ด๋ผ๋ ๊ฐ์ ์ฐ์ถํฉ๋๋ค.
์ผ๋ฐ์ ์ธ ์ํ ํ๊ธฐ๋ฒ๊ณผ ๋๋ถ๋ถ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๊ฐ ํจ์๋ฅผ ์ธ์์ ์ ์ฉํ๊ธฐ ์ํด ๊ดํธ(์: f(x))๋ฅผ ์ฌ์ฉํ๋ ๋ฐ๋ฉด, Lean์ ๋จ์ํ ํจ์๋ฅผ ์ธ์ ์์ ์๋๋ค(์: f x). ํจ์ ์ ์ฉ์ ๊ฐ์ฅ ํํ ์ฐ์ฐ ์ค ํ๋์ด๋ฏ๋ก ๊ฐ๊ฒฐํ๊ฒ ์ ์งํ๋ ๊ฒ์ด ์ข์ต๋๋ค. "Hello, Lean!"์ ๊ณ์ฐํ๊ธฐ ์ํด
#eval String.append("Hello, ", "Lean!")
๋ผ๊ณ ์ฐ๋ ๋์ , ๋ค์๊ณผ ๊ฐ์ด ์๋๋ค.
#eval String.append "Hello, " "Lean!"
์ฌ๊ธฐ์ ํจ์์ ๋ ์ธ์๋ ๋จ์ํ ๊ณต๋ฐฑ์ผ๋ก ๊ตฌ๋ถํ์ฌ ์์ ์๋๋ค.
์ฐ์ ์ ์ฐ์ฐ ์์ ๊ท์น์ด (1 + 2) * 5 ํํ์์์ ๊ดํธ๋ฅผ ์๊ตฌํ๋ ๊ฒ์ฒ๋ผ, ํจ์์ ์ธ์๊ฐ ๋ค๋ฅธ ํจ์ ํธ์ถ์ ํตํด ๊ณ์ฐ๋์ด์ผ ํ ๋๋ ๊ดํธ๊ฐ ํ์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์ ํํ์์์๋ ๊ดํธ๊ฐ ํ์ํฉ๋๋ค.
#eval String.append "great " (String.append "oak " "tree")
๊ทธ๋ ์ง ์์ผ๋ฉด ๋ ๋ฒ์งธ String.append๋ "oak "์ "tree"๋ฅผ ์ธ์๋ก ๋ฐ๋ ํจ์๊ฐ ์๋๋ผ ์ฒซ ๋ฒ์งธ String.append์ ์ธ์๋ก ํด์๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ด๋ถ String.append ํธ์ถ์ ๊ฐ์ ๋จผ์ ์ฐพ์์ผ ํ๋ฉฐ, ๊ทธ ํ์ "great "์ ๋ง๋ถ์ฌ์ ธ ์ต์ข
๊ฐ "great oak tree"๋ฅผ ์ฐ์ถํ ์ ์์ต๋๋ค.
๋ช
๋ นํ ์ธ์ด๋ ์ข
์ข
๋ ์ข
๋ฅ์ ์กฐ๊ฑด๋ฌธ์ ๊ฐ์ง๋๋ค. ํ๋๋ ๋ถ๋ฆฌ์ธ ๊ฐ์ ๋ฐ๋ผ ์ด๋ค ๋ช
๋ น์ ์ํํ ์ง ๊ฒฐ์ ํ๋ ์กฐ๊ฑด๋ฌธ์ด๊ณ , ๋ค๋ฅธ ํ๋๋ ๋ถ๋ฆฌ์ธ ๊ฐ์ ๋ฐ๋ผ ๋ ํํ์ ์ค ์ด๋ ๊ฒ์ ํ๊ฐํ ์ง ๊ฒฐ์ ํ๋ ์กฐ๊ฑด ํํ์์
๋๋ค. ์๋ฅผ ๋ค์ด, C์ C++์์๋ ์กฐ๊ฑด๋ฌธ์ด if์ else๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๋๋ ๋ฐ๋ฉด, ์กฐ๊ฑด ํํ์์ ?์ :๊ฐ ์กฐ๊ฑด์ ๋ถ๊ธฐ์์ ๋ถ๋ฆฌํ๋ ์ผํญ ์ฐ์ฐ์๋ก ์์ฑ๋ฉ๋๋ค. ํ์ด์ฌ์์๋ ์กฐ๊ฑด๋ฌธ์ด if๋ก ์์ํ๋ ๋ฐ๋ฉด, ์กฐ๊ฑด ํํ์์ if๋ฅผ ์ค๊ฐ์ ๋ก๋๋ค. Lean์ ํํ์ ์ค์ฌ์ ํจ์ํ ์ธ์ด์ด๊ธฐ ๋๋ฌธ์ ์กฐ๊ฑด๋ฌธ์ ์๊ณ ์กฐ๊ฑด ํํ์๋ง ์์ต๋๋ค. ์ด๊ฒ๋ค์ if, then, else๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด,String.append "it is " (if 1 > 2 then "yes" else "no")
๋ ๋ค์๊ณผ ๊ฐ์ด ํ๊ฐ๋ฉ๋๋ค.String.append "it is " (if false then "yes" else "no")
์ด๋ ๋ค์ ๋ค์๊ณผ ๊ฐ์ด ํ๊ฐ๋ฉ๋๋ค.String.append "it is " "no"
๊ทธ๋ฆฌ๊ณ ์ต์ข
์ ์ผ๋ก "it is no"๋ก ํ๊ฐ๋ฉ๋๋ค.
๊ฐ๊ฒฐํจ์ ์ํด, ์ด์ ๊ฐ์ ์ผ๋ จ์ ํ๊ฐ ๋จ๊ณ๋ ๋๋๋ก ํ์ดํ๋ก ์ฐ๊ฒฐํ์ฌ ์์ฑ๋ ์ ์์ต๋๋ค.String.append "it is " (if 1 > 2 then "yes" else "no")String.append "it is " (if false then "yes" else "no")String.append "it is " "no""it is no"
1.1.1. ๋ง์ฃผ์น ์ ์๋ ๋ฉ์์ง
์ธ์๊ฐ ๋๋ฝ๋ ํจ์ ์ ์ฉ์ Lean์๊ฒ ํ๊ฐํ๋๋ก ์์ฒญํ๋ฉด ์ค๋ฅ ๋ฉ์์ง๊ฐ ๋ฐ์ํฉ๋๋ค. ํนํ, ๋ค์ ์์ ๋
#eval String.append "it is "
์๋นํ ๊ธด ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ฐ์ถํฉ๋๋ค.
could not synthesize a `ToExpr`, `Repr`, or `ToString` instance for type String โ String
์ด ๋ฉ์์ง๋ Lean ํจ์๊ฐ ์ผ๋ถ ์ธ์์๋ง ์ ์ฉ๋ ๋ ๋๋จธ์ง ์ธ์๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์๋ก์ด ํจ์๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. Lean์ ํจ์๋ฅผ ์ฌ์ฉ์์๊ฒ ํ์ํ ์ ์์ผ๋ฏ๋ก, ๊ทธ๋ ๊ฒ ํ๋๋ก ์์ฒญ๋ฐ์์ ๋ ์ค๋ฅ๋ฅผ ๋ฐํํฉ๋๋ค.
1.1.2. ์ฐ์ต ๋ฌธ์
๋ค์ ํํ์๋ค์ ๊ฐ์ ๋ฌด์์ผ๊น์? ์์ผ๋ก ํ์ด๋ณธ ๋ค์, Lean์ ์
๋ ฅํ์ฌ ๋ต์ ํ์ธํด ๋ณด์ธ์.
42 + 19
String.append "A" (String.append "B" "C")
String.append (String.append "A" "B") "C"
if 3 == 3 then 5 else 7
if 3 == 4 then "equal" else "not equal"
1.2. ํ์
ํ์
์ ํ๋ก๊ทธ๋จ์ด ๊ณ์ฐํ ์ ์๋ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ํ๋ก๊ทธ๋จ์ ๋ถ๋ฅํฉ๋๋ค. ํ์
์ ํ๋ก๊ทธ๋จ์์ ์ฌ๋ฌ ์ญํ ์ ์ํํฉ๋๋ค.
์ปดํ์ผ๋ฌ๊ฐ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋ด ํํ์ ๋ํด ๊ฒฐ์ ํ ์ ์๊ฒ ํฉ๋๋ค.
ํ๋ก๊ทธ๋๋จธ๊ฐ ๋ค๋ฅธ ์ฌ๋์๊ฒ ์์ ์ ์๋๋ฅผ ์ ๋ฌํ๋ ๋ฐ ๋์์ ์ฃผ๋ฉฐ, ํจ์์ ์
๋ ฅ๊ณผ ์ถ๋ ฅ์ ๋ํ ๊ฐ๋ฒผ์ด ๋ช
์ธ ์ญํ ์ ํฉ๋๋ค. ์ปดํ์ผ๋ฌ๋ ํ๋ก๊ทธ๋จ์ด ์ด ๋ช
์ธ๋ฅผ ์ค์ํ๋๋ก ๋ณด์ฅํฉ๋๋ค.
์ซ์์ ๋ฌธ์์ด์ ๋ํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ค์ํ ์ ์ฌ์ ์ค์๋ฅผ ๋ฐฉ์งํ์ฌ ํ๋ก๊ทธ๋จ์ ํ์ํ ํ
์คํธ์ ์๋ฅผ ์ค์ฌ์ค๋๋ค.
Lean ์ปดํ์ผ๋ฌ๊ฐ ์์ฉ๊ตฌ ์ฝ๋๋ฅผ ์ ์ฝํ ์ ์๋ ๋ณด์กฐ ์ฝ๋ ์์ฑ์ ์๋ํํ๋ ๋ฐ ๋์์ ์ค๋๋ค.
Lean์ ํ์
์์คํ
์ ์ด๋ก์ ์ผ๋ก ํํ๋ ฅ์ด ํ๋ถํฉ๋๋ค. ํ์
์ "์ด ์ ๋ ฌ ํจ์๋ ์
๋ ฅ์ ์์ด์ ๋ฐํํ๋ค"์ ๊ฐ์ ๊ฐ๋ ฅํ ๋ช
์ธ๋ "์ด ํจ์๋ ์ธ์์ ๊ฐ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฐํ ํ์
์ ๊ฐ๋๋ค"์ ๊ฐ์ ์ ์ฐํ ๋ช
์ธ๋ฅผ ์ธ์ฝ๋ฉํ ์ ์์ต๋๋ค. ํ์
์์คํ
์ ์ฌ์ง์ด ์ํ์ ์ ๋ฆฌ๋ฅผ ์ฆ๋ช
ํ๊ธฐ ์ํ ์์ ํ ๋
ผ๋ฆฌ๋ก๋ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ์ต์ฒจ๋จ ํํ๋ ฅ์ด ๋ ๊ฐ๋จํ ํ์
์ ๋ถํ์ํ๊ฒ ๋ง๋๋ ๊ฒ์ ์๋๋ฉฐ, ์ด๋ฌํ ๋ ๊ฐ๋จํ ํ์
์ ์ดํดํ๋ ๊ฒ์ด ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํ ์ ์ ์กฐ๊ฑด์
๋๋ค.
Lean์ ๋ชจ๋ ํ๋ก๊ทธ๋จ์ ํ์
์ ๊ฐ์ ธ์ผ ํฉ๋๋ค. ํนํ, ๋ชจ๋ ํํ์์ ํ๊ฐ๋๊ธฐ ์ ์ ํ์
์ ๊ฐ์ ธ์ผ ํฉ๋๋ค. ์ง๊ธ๊น์ง์ ์์ ์์๋ Lean์ด ์ค์ค๋ก ํ์
์ ๋ฐ๊ฒฌํ ์ ์์์ง๋ง, ๋๋ก๋ ํ์
์ ์ ๊ณตํด์ผ ํ ํ์๊ฐ ์์ต๋๋ค. ์ด๋ ๊ดํธ ์์์ ์ฝ๋ก ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฉ๋๋ค.
#eval (1 + 2 : Nat)
์ฌ๊ธฐ์ Nat์ ์์ฐ์์ ํ์
์ผ๋ก, ์์ ์ ๋ฐ๋์ ๋ถํธ ์๋ ์ ์์
๋๋ค. Lean์์ Nat์ ์์๊ฐ ์๋ ์ ์ ๋ฆฌํฐ๋ด์ ๊ธฐ๋ณธ ํ์
์
๋๋ค. ์ด ๊ธฐ๋ณธ ํ์
์ด ํญ์ ์ต์ ์ ์ ํ์ ์๋๋๋ค. C์์๋ ๋ถํธ ์๋ ์ ์๊ฐ ๋บ์
๊ฒฐ๊ณผ๊ฐ 0๋ณด๋ค ์์์ง ๊ฒฝ์ฐ ํํ ๊ฐ๋ฅํ ๊ฐ์ฅ ํฐ ์๋ก ์ธ๋ํ๋ก์ฐ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ Nat์ ์์๋ก ํฐ ๋ถํธ ์๋ ์๋ฅผ ํํํ ์ ์์ผ๋ฏ๋ก ์ธ๋ํ๋ก์ฐ๋ ๊ฐ์ฅ ํฐ ์๊ฐ ์์ต๋๋ค. ๋ฐ๋ผ์ Nat์์์ ๋บ์
์ ๊ฒฐ๊ณผ๊ฐ ์์์์ ๊ฒฝ์ฐ 0์ ๋ฐํํฉ๋๋ค. ์๋ฅผ ๋ค์ด,
#eval (1 - 2 : Nat)
๋ -1์ด ์๋ 0์ผ๋ก ํ๊ฐ๋ฉ๋๋ค. ์์ ์ ์๋ฅผ ํํํ ์ ์๋ ํ์
์ ์ฌ์ฉํ๋ ค๋ฉด ์ง์ ์ ๊ณตํ์ญ์์ค.
#eval (1 - 2 : Int)
์ด ํ์
์ ์ฌ์ฉํ๋ฉด ๊ฒฐ๊ณผ๋ ์์๋๋ก -1์ด ๋ฉ๋๋ค.
ํํ์์ ํ๊ฐํ์ง ์๊ณ ํ์
์ ํ์ธํ๋ ค๋ฉด #eval ๋์ #check๋ฅผ ์ฌ์ฉํ์ญ์์ค. ์๋ฅผ ๋ค์ด:
#check (1 - 2 : Int)
๋ ์ค์ ๋ก ๋บ์
์ ์ํํ์ง ์๊ณ 1 - 2 : Int๋ฅผ ๋ณด๊ณ ํฉ๋๋ค.
ํ๋ก๊ทธ๋จ์ ํ์
์ ๋ถ์ฌํ ์ ์์ ๋๋ #check์ #eval ๋ชจ๋์์ ์ค๋ฅ๊ฐ ๋ฐํ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด:
#check String.append ["hello", " "] "world"
๋ ๋ค์๊ณผ ๊ฐ์ด ์ถ๋ ฅํฉ๋๋ค.
Application type mismatch: The argument ["hello", " "]has type List Stringbut is expected to have type Stringin the application String.append ["hello", " "]
String.append์ ์ฒซ ๋ฒ์งธ ์ธ์๋ ๋ฌธ์์ด์ด์ด์ผ ํ๋๋ฐ ๋ฌธ์์ด ๋ฆฌ์คํธ๊ฐ ๋์ ์ ๊ณต๋์๊ธฐ ๋๋ฌธ์
๋๋ค.
1.3. ํจ์์ ์ ์
Lean์์๋ def ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ์๋ฅผ ๋์
ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, hello๋ผ๋ ์ด๋ฆ์ ๋ฌธ์์ด "Hello"๋ฅผ ์ฐธ์กฐํ๋๋ก ์ ์ํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์์ฑํฉ๋๋ค.
def hello := "Hello"
Lean์์๋ ์๋ก์ด ์ด๋ฆ์ ์ ์ํ ๋ = ๋์ ์ฝ๋ก -๋ฑํธ ์ฐ์ฐ์ :=๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ =๊ฐ ๊ธฐ์กด ํํ์ ๊ฐ์ ๋๋ฑ์ฑ์ ์ค๋ช
ํ๋ ๋ฐ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ด๋ฉฐ, ๋ ๊ฐ์ ๋ค๋ฅธ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ฉด ํผ๋์ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
hello์ ์ ์์์, ํํ์ "Hello"๋ Lean์ด ์ ์์ ํ์
์ ์๋์ผ๋ก ๊ฒฐ์ ํ ์ ์์ ๋งํผ ์ถฉ๋ถํ ๊ฐ๋จํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ถ๋ถ์ ์ ์๋ ๊ทธ๋ ๊ฒ ๊ฐ๋จํ์ง ์์ผ๋ฏ๋ก, ๋ณดํต ํ์
์ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ์ด๋ ์ ์๋๋ ์ด๋ฆ ๋ค์ ์ฝ๋ก ์ ์ฌ์ฉํ์ฌ ์ํ๋ฉ๋๋ค.
def lean : String := "Lean"
์ด์ ์ด๋ฆ์ด ์ ์๋์์ผ๋ฏ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์
#eval String.append hello (String.append " " lean)
์ ๋ค์๊ณผ ๊ฐ์ด ์ถ๋ ฅ๋ฉ๋๋ค.
"Hello Lean"
Lean์์๋ ์ ์๋ ์ด๋ฆ์ ์ ์๋ ์ดํ์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ง์ ์ธ์ด์์ ํจ์ ์ ์๋ ๋ค๋ฅธ ๊ฐ์ ์ ์์ ๋ค๋ฅธ ๊ตฌ๋ฌธ์ ์ฌ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํ์ด์ฌ ํจ์ ์ ์๋ def ํค์๋๋ก ์์ํ๋ ๋ฐ๋ฉด, ๋ค๋ฅธ ์ ์๋ ๋ฑํธ๋ก ์ ์๋ฉ๋๋ค. Lean์์๋ ํจ์๋ฅผ ๋ค๋ฅธ ๊ฐ๊ณผ ๋์ผํ def ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ํฉ๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ , hello์ ๊ฐ์ ์ ์๋ ํธ์ถ๋ ๋๋ง๋ค ๋๋ฑํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ ์ธ์๊ฐ ์๋ ํจ์๊ฐ ์๋๋ผ, ๊ทธ ๊ฐ ์์ฒด๋ฅผ ์ง์ ์ฐธ์กฐํ๋ ์ด๋ฆ์ ๋์
ํฉ๋๋ค.
1.3.1. ํจ์ ์ ์ํ๊ธฐ
Lean์์ ํจ์๋ฅผ ์ ์ํ๋ ๋ฐฉ๋ฒ์ ๋ค์ํฉ๋๋ค. ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ํจ์์ ์ธ์๋ฅผ ์ ์์ ํ์
์์ ๊ณต๋ฐฑ์ผ๋ก ๊ตฌ๋ถํ์ฌ ๋ฐฐ์นํ๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, ์ธ์์ 1์ ๋ํ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
def add1 (n : Nat) : Nat := n + 1
#eval๋ก ์ด ํจ์๋ฅผ ํ
์คํธํ๋ฉด ์์๋๋ก 8์ด ๋์ต๋๋ค.
#eval add1 7
ํจ์๊ฐ ๊ฐ ์ธ์ ์ฌ์ด์ ๊ณต๋ฐฑ์ ์จ์ ์ฌ๋ฌ ์ธ์์ ์ ์ฉ๋๋ ๊ฒ์ฒ๋ผ, ์ฌ๋ฌ ์ธ์๋ฅผ ๋ฐ๋ ํจ์๋ ์ธ์์ ์ด๋ฆ๊ณผ ํ์
์ฌ์ด์ ๊ณต๋ฐฑ์ ๋์ด ์ ์๋ฉ๋๋ค. maximum ํจ์๋ ๋ ์ธ์ n๊ณผ k ์ค ๋ ํฐ ๊ฐ๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ฉฐ, ๋ ๊ฐ์ Nat ์ธ์๋ฅผ ๋ฐ์ Nat๋ฅผ ๋ฐํํฉ๋๋ค.
def maximum (n : Nat) (k : Nat) : Nat := if n < k then k else n
๋ง์ฐฌ๊ฐ์ง๋ก, spaceBetween ํจ์๋ ๋ ๋ฌธ์์ด ์ฌ์ด์ ๊ณต๋ฐฑ์ ๋ฃ์ด ๊ฒฐํฉํฉ๋๋ค.
def spaceBetween (before : String) (after : String) : String := String.append before (String.append " " after)
maximum๊ณผ ๊ฐ์ ์ ์๋ ํจ์์ ์ธ์๊ฐ ์ ๊ณต๋๋ฉด, ๊ฒฐ๊ณผ๋ ๋จผ์ ๋ณธ๋ฌธ์์ ์ธ์ ์ด๋ฆ์ ์ ๊ณต๋ ๊ฐ์ผ๋ก ๋ฐ๊พผ ๋ค์, ๊ฒฐ๊ณผ ๋ณธ๋ฌธ์ ํ๊ฐํ์ฌ ๊ฒฐ์ ๋ฉ๋๋ค. ์๋ฅผ ๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
maximum (5 + 8) (2 * 7)
โ
โโนโ
โ\implies
maximum 13 14
โ
โโนโ
โ\implies
if 13 < 14 then 14 else 13
โ
โโนโ
โ\implies
14
์์ฐ์, ์ ์, ๋ฌธ์์ด๋ก ํ๊ฐ๋๋ ํํ์์ ์ด๋ฅผ ๋ํ๋ด๋ ํ์
(Nat, Int, String ๋ฑ)์ ๊ฐ์ง๋๋ค. ์ด๋ ํจ์์๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. Nat๋ฅผ ๋ฐ์ Bool์ ๋ฐํํ๋ ํจ์๋ Nat โ Bool ํ์
์ ๊ฐ์ง๋ฉฐ, ๋ ๊ฐ์ Nat๋ฅผ ๋ฐ์ Nat๋ฅผ ๋ฐํํ๋ ํจ์๋ Nat โ Nat โ Nat ํ์
์ ๊ฐ์ง๋๋ค.
ํน๋ณํ ๊ฒฝ์ฐ๋ก, Lean์ #check์ ํจ๊ป ์ด๋ฆ์ด ์ง์ ์ฌ์ฉ๋ ๋ ํจ์์ ์๊ทธ๋์ฒ๋ฅผ ๋ฐํํฉ๋๋ค. #check add1์ ์
๋ ฅํ๋ฉด add1 (n : Nat) : Nat๊ฐ ๋์ต๋๋ค. ๊ทธ๋ฌ๋ ํจ์์ ์ด๋ฆ์ ๊ดํธ ์์ ์จ์ ํจ์๋ฅผ ์ผ๋ฐ ํํ์์ผ๋ก ์ทจ๊ธํ๊ฒ ํจ์ผ๋ก์จ Lean์ "์์ฌ" ํจ์์ ํ์
์ ํ์ํ๊ฒ ํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ #check (add1)์ add1 : Nat โ Nat๋ฅผ, #check (maximum)์ maximum : Nat โ Nat โ Nat๋ฅผ ์ฐ์ถํฉ๋๋ค. ์ด ํ์ดํ๋ ASCII ๋์ฒด ํ์ดํ ->๋ก๋ ์ธ ์ ์์ผ๋ฏ๋ก, ์์ ํจ์ ํ์
์ ๊ฐ๊ฐ example : Nat -> Nat := add1๊ณผ example : Nat -> Nat -> Nat := maximum์ผ๋ก ์ธ ์ ์์ต๋๋ค.
๋ด๋ถ์ ์ผ๋ก ๋ชจ๋ ํจ์๋ ์ค์ ๋ก๋ ์ ํํ ํ๋์ ์ธ์๋ฅผ ๊ธฐ๋ํฉ๋๋ค. maximum์ฒ๋ผ ์ฌ๋ฌ ์ธ์๋ฅผ ๋ฐ๋ ๊ฒ์ฒ๋ผ ๋ณด์ด๋ ํจ์๋ ์ฌ์ค ํ๋์ ์ธ์๋ฅผ ๋ฐ๊ณ ์๋ก์ด ํจ์๋ฅผ ๋ฐํํ๋ ํจ์์
๋๋ค. ์ด ์๋ก์ด ํจ์๋ ๋ค์ ์ธ์๋ฅผ ๋ฐ๊ณ , ๋ ์ด์ ๊ธฐ๋๋๋ ์ธ์๊ฐ ์์ ๋๊น์ง ์ด ๊ณผ์ ์ด ๊ณ์๋ฉ๋๋ค. ์ด๋ ์ฌ๋ฌ ์ธ์๋ฅผ ๋ฐ๋ ํจ์์ ํ๋์ ์ธ์๋ฅผ ์ ๊ณตํจ์ผ๋ก์จ ํ์ธํ ์ ์์ต๋๋ค. #check maximum 3์ maximum 3 : Nat โ Nat๋ฅผ, #check spaceBetween "Hello "๋ spaceBetween "Hello " : String โ String์ ์ฐ์ถํฉ๋๋ค. ํจ์๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ค์ค ์ธ์ ํจ์๋ฅผ ๊ตฌํํ๋ ๊ฒ์ ์ํ์ ํ์ค์ผ ์ปค๋ฆฌ์ ์ด๋ฆ์ ๋ฐ์ ์ปค๋ง(currying)์ด๋ผ๊ณ ํฉ๋๋ค. ํจ์ ํ์ดํ๋ ์ค๋ฅธ์ชฝ์ผ๋ก ๊ฒฐํฉํ๋ฏ๋ก, Nat โ Nat โ Nat๋ Nat โ (Nat โ Nat)๋ก ๊ดํธ๋ฅผ ์ณ์ผ ํฉ๋๋ค.
1.3.1.1. ์ฐ์ต ๋ฌธ์
String โ String โ String โ String ํ์
์ joinStringsWith ํจ์๋ฅผ ์ ์ํ์ธ์. ์ด ํจ์๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ฅผ ๋ ๋ฒ์งธ์ ์ธ ๋ฒ์งธ ์ธ์ ์ฌ์ด์ ๋ฃ์ด ์๋ก์ด ๋ฌธ์์ด์ ๋ง๋ญ๋๋ค. joinStringsWith ", " "one" "and another"๋ "one, and another"๋ก ํ๊ฐ๋์ด์ผ ํฉ๋๋ค.
joinStringsWith ": "์ ํ์
์ ๋ฌด์์ผ๊น์? Lean์ผ๋ก ๋ต์ ํ์ธํด ๋ณด์ธ์.
์ฃผ์ด์ง ๋์ด, ๋๋น, ๊น์ด๋ก ์ง์ก๋ฉด์ฒด์ ๋ถํผ๋ฅผ ๊ณ์ฐํ๋ Nat โ Nat โ Nat โ Nat ํ์
์ volume ํจ์๋ฅผ ์ ์ํ์ธ์.
1.3.2. ํ์
์ ์ํ๊ธฐ
๋๋ถ๋ถ์ ํ์
์ด ์๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์๋ C์ typedef์ ๊ฐ์ด ํ์
์ ๋ํ ๋ณ์นญ์ ์ ์ํ๋ ์๋จ์ด ์์ต๋๋ค. ๊ทธ๋ฌ๋ Lean์์๋ ํ์
์ด ์ธ์ด์ ์ผ๊ธ(first-class) ๊ตฌ์ฑ ์์์
๋๋ค. ์ฆ, ํ์
์ ๋ค๋ฅธ ํํ์๊ณผ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ์ด๋ ์ ์๊ฐ ๋ค๋ฅธ ๊ฐ๋ฟ๋ง ์๋๋ผ ํ์
๋ ์ฐธ์กฐํ ์ ์์์ ์๋ฏธํฉ๋๋ค.
์๋ฅผ ๋ค์ด, String์ ์
๋ ฅํ๊ธฐ๊ฐ ๋๋ฌด ๊ธธ๋ค๋ฉด, ๋ ์งง์ ์ฝ์ด Str์ ์ ์ํ ์ ์์ต๋๋ค.
def Str : Type := String
๊ทธ๋ฌ๋ฉด String ๋์ Str์ ์ ์์ ํ์
์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
def aStr : Str := "This is a string."
์ด๊ฒ์ด ์๋ํ๋ ์ด์ ๋ ํ์
์ด Lean์ ๋๋จธ์ง ๋ถ๋ถ๊ณผ ๋์ผํ ๊ท์น์ ๋ฐ๋ฅด๊ธฐ ๋๋ฌธ์
๋๋ค. ํ์
์ ํํ์์ด๋ฉฐ, ํํ์์์ ์ ์๋ ์ด๋ฆ์ ๊ทธ ์ ์๋ก ๋์ฒด๋ ์ ์์ต๋๋ค. Str์ด String์ ์๋ฏธํ๋๋ก ์ ์๋์๊ธฐ ๋๋ฌธ์ aStr์ ์ ์๋ ํ๋นํฉ๋๋ค.
1.3.2.1. ๋ง์ฃผ์น ์ ์๋ ๋ฉ์์ง
ํ์
์ ๋ํ ์ ์๋ฅผ ์ฌ์ฉํ๋ ์คํ์ Lean์ด ์ค๋ฒ๋ก๋๋ ์ ์ ๋ฆฌํฐ๋ด์ ์ง์ํ๋ ๋ฐฉ์ ๋๋ฌธ์ ๋ ๋ณต์กํด์ง๋๋ค. Nat์ด ๋๋ฌด ์งง๋ค๋ฉด, ๋ ๊ธด ์ด๋ฆ NaturalNumber๋ฅผ ์ ์ํ ์ ์์ต๋๋ค.def NaturalNumber : Type := Nat
๊ทธ๋ฌ๋ Nat ๋์ NaturalNumber๋ฅผ ์ ์์ ํ์
์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ ์์๋๋ก ์๋ํ์ง ์์ต๋๋ค. ํนํ, ๋ค์ ์ ์๋:def thirtyEight : NaturalNumber := 38
๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค.
failed to synthesize OfNat NaturalNumber 38numerals are polymorphic in Lean, but the numeral `38` cannot be used in a context where the expected type is NaturalNumberdue to the absence of the instance aboveHint: Additional diagnostic information may be available using the `set_option diagnostics true` command.
์ด ์ค๋ฅ๋ Lean์ด ์ซ์ ๋ฆฌํฐ๋ด์ ์ค๋ฒ๋ก๋ํ ์ ์๋๋ก ํ์ฉํ๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. ํ๋นํ ๊ฒฝ์ฐ, ์์ฐ์ ๋ฆฌํฐ๋ด์ ๋ง์น ํด๋น ํ์
์ด ์์คํ
์ ๋ด์ฅ๋ ๊ฒ์ฒ๋ผ ์๋ก์ด ํ์
์ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ์ด๊ฒ์ ์ํ์ ํธ๋ฆฌํ๊ฒ ํํํ๋ ค๋ Lean์ ๋ชฉํ์ ์ผ๋ถ์ด๋ฉฐ, ์ํ์ ๋ค๋ฅธ ๋ถ์ผ์์๋ ์ซ์ ํ๊ธฐ๋ฒ์ ๋งค์ฐ ๋ค๋ฅธ ๋ชฉ์ ์ผ๋ก ์ฌ์ฉํฉ๋๋ค. ์ด ์ค๋ฒ๋ก๋ฉ์ ํ์ฉํ๋ ํน์ ๊ธฐ๋ฅ์ ์ค๋ฒ๋ก๋ฉ์ ์ฐพ๊ธฐ ์ ์ ๋ชจ๋ ์ ์๋ ์ด๋ฆ์ ๊ทธ ์ ์๋ก ๋์ฒดํ์ง ์๊ธฐ ๋๋ฌธ์ ์์ ๊ฐ์ ์ค๋ฅ ๋ฉ์์ง๊ฐ ๋ฐ์ํฉ๋๋ค.
์ด ์ ํ์ ํด๊ฒฐํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ์์ ์ค๋ฅธ์ชฝ์ Nat ํ์
์ ์ ๊ณตํ์ฌ 38์ ๋ํด Nat์ ์ค๋ฒ๋ก๋ฉ ๊ท์น์ด ์ฌ์ฉ๋๋๋ก ํ๋ ๊ฒ์
๋๋ค.
def thirtyEight : NaturalNumber := (38 : Nat)
NaturalNumber๋ ์ ์์ ๋ฐ๋ผ Nat์ ๋์ผํ ํ์
์ด๋ฏ๋ก ์ด ์ ์๋ ์ฌ์ ํ ํ์
์ด ์ฌ๋ฐ๋ฆ
๋๋ค!
๋ ๋ค๋ฅธ ํด๊ฒฐ์ฑ
์ Nat์ ๋ํ ์ค๋ฒ๋ก๋ฉ๊ณผ ๋๋ฑํ๊ฒ ์๋ํ๋ NaturalNumber์ ๋ํ ์ค๋ฒ๋ก๋ฉ์ ์ ์ํ๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฅผ ์ํด์๋ Lean์ ๋ ๊ณ ๊ธ ๊ธฐ๋ฅ์ด ํ์ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก, def ๋์ abbrev๋ฅผ ์ฌ์ฉํ์ฌ Nat์ ๋ํ ์ ์ด๋ฆ์ ์ ์ํ๋ฉด ์ค๋ฒ๋ก๋ฉ ํด๊ฒฐ ๊ณผ์ ์์ ์ ์๋ ์ด๋ฆ์ด ๊ทธ ์ ์๋ก ๋์ฒด๋ ์ ์์ต๋๋ค. abbrev๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ๋ ์ ์๋ ํญ์ ์ ๊ฐ(unfold)๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์์ ๋ฌธ์ ์์ด ๋ฐ์๋ค์ฌ์ง๋๋ค.
abbrev N : Type := Natdef thirtyNine : N := 39
๋ด๋ถ์ ์ผ๋ก ์ผ๋ถ ์ ์๋ ์ค๋ฒ๋ก๋ฉ ํด๊ฒฐ ์ค์ ์ ๊ฐ ๊ฐ๋ฅํ๋๋ก ํ์๋๋ ๋ฐ๋ฉด, ๋ค๋ฅธ ์ ์๋ ๊ทธ๋ ์ง ์์ต๋๋ค. ์ ๊ฐ๋ ์ ์๋ฅผ ์ถ์ฝ ๊ฐ๋ฅ(reducible)ํ๋ค๊ณ ํฉ๋๋ค. ์ถ์ฝ ๊ฐ๋ฅ์ฑ์ ๋ํ ์ ์ด๋ Lean์ด ํ์ฅ์ฑ์ ๊ฐ์ถ๊ธฐ ์ํด ํ์์ ์
๋๋ค. ๋ชจ๋ ์ ์๋ฅผ ์์ ํ ์ ๊ฐํ๋ฉด ๊ธฐ๊ณ๊ฐ ์ฒ๋ฆฌํ๊ธฐ์ ๋๋ฆฌ๊ณ ์ฌ์ฉ์๊ฐ ์ดํดํ๊ธฐ ์ด๋ ค์ด ๋งค์ฐ ํฐ ํ์
์ด ๋ ์ ์์ต๋๋ค. abbrev๋ก ์์ฑ๋ ์ ์๋ ์ถ์ฝ ๊ฐ๋ฅ์ผ๋ก ํ์๋ฉ๋๋ค.
1.4. ๊ตฌ์กฐ์ฒด
ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ ์ฒซ ๋จ๊ณ๋ ๋ณดํต ๋ฌธ์ ์์ญ์ ๊ฐ๋
์ ํ์
ํ ๋ค์, ์ฝ๋์์ ์ด๋ฅผ ์ ์ ํ๊ฒ ํํํ๋ ๋ฐฉ๋ฒ์ ์ฐพ๋ ๊ฒ์
๋๋ค. ๋๋ก๋ ๋๋ฉ์ธ ๊ฐ๋
์ด ๋ค๋ฅธ ๋ ๊ฐ๋จํ ๊ฐ๋
๋ค์ ์งํฉ์ผ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ, ์ด๋ฌํ ๋ ๊ฐ๋จํ ๊ตฌ์ฑ ์์๋ค์ ํ๋์ "ํจํค์ง"๋ก ๋ฌถ์ด ์๋ฏธ ์๋ ์ด๋ฆ์ ๋ถ์ฌํ๋ ๊ฒ์ด ํธ๋ฆฌํ ์ ์์ต๋๋ค. Lean์์๋ ์ด๋ฅผ ๊ตฌ์กฐ์ฒด(structure)๋ฅผ ์ฌ์ฉํ์ฌ ์ํํ๋ฉฐ, ์ด๋ C๋ Rust์ struct, C#์ record์ ์ ์ฌํฉ๋๋ค.
๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํ๋ฉด Lean์ ์์ ํ ์๋ก์ด ํ์
์ด ๋์
๋๋ฉฐ, ์ด ํ์
์ ๋ค๋ฅธ ์ด๋ค ํ์
์ผ๋ก๋ ํ์๋ ์ ์์ต๋๋ค. ์ด๋ ์ฌ๋ฌ ๊ตฌ์กฐ์ฒด๊ฐ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๋๋ผ๋ ์๋ก ๋ค๋ฅธ ๊ฐ๋
์ ๋ํ๋ผ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํ ์ ์ ์ง๊ต์ขํ๊ณ๋ ๊ทน์ขํ๊ณ๋ฅผ ์ฌ์ฉํ์ฌ ํํ๋ ์ ์์ผ๋ฉฐ, ๊ฐ๊ฐ์ ํ ์์ ๋ถ๋์์์ ์ซ์๋ก ์ด๋ฃจ์ด์ง๋๋ค. ๋ณ๋์ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํ๋ฉด API ํด๋ผ์ด์ธํธ๊ฐ ํ๋๋ฅผ ๋ค๋ฅธ ๊ฒ์ผ๋ก ํผ๋ํ๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
Lean์ ๋ถ๋์์์ ์ซ์ ํ์
์ Float์ด๋ผ๊ณ ํ๋ฉฐ, ๋ถ๋์์์ ์ซ์๋ ์ผ๋ฐ์ ์ธ ํ๊ธฐ๋ฒ์ผ๋ก ์์ฑ๋ฉ๋๋ค.
#check 1.21.2 : Float#check -454.2123215-454.2123215 : Float#check 0.00.0 : Float
๋ถ๋์์์ ์ซ์๋ฅผ ์์์ ๊ณผ ํจ๊ป ์์ฑํ๋ฉด Lean์ Float ํ์
์ ์ถ๋ก ํฉ๋๋ค. ์์์ ์์ด ์์ฑํ๋ฉด ํ์
๋ช
์๊ฐ ํ์ํ ์ ์์ต๋๋ค.
#check 00 : Nat#check (0 : Float)0 : Float
์ง๊ต์ขํ๊ณ์ ์ ์ x์ y๋ผ๋ ๋ ๊ฐ์ Float ํ๋๋ฅผ ๊ฐ์ง ๊ตฌ์กฐ์ฒด์
๋๋ค. ์ด๋ structure ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ธ๋ฉ๋๋ค.
structure Point where x : Float y : Float
์ด ์ ์ธ ์ดํ, Point๋ ์๋ก์ด ๊ตฌ์กฐ์ฒด ํ์
์ด ๋ฉ๋๋ค. ๊ตฌ์กฐ์ฒด ํ์
์ ๊ฐ์ ๋ง๋๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์ ์ค๊ดํธ ์์ ๋ชจ๋ ํ๋์ ๋ํ ๊ฐ์ ์ ๊ณตํ๋ ๊ฒ์
๋๋ค. ๋ฐ์นด๋ฅดํธ ํ๋ฉด์ ์์ ์ x์ y๊ฐ ๋ชจ๋ 0์ธ ๊ณณ์
๋๋ค.
def origin : Point := { x := 0.0, y := 0.0 }
#eval origin์ ๊ฒฐ๊ณผ๋ origin์ ์ ์์ ๋งค์ฐ ์ ์ฌํ๊ฒ ๋ณด์
๋๋ค.
{ x := 0.000000, y := 0.000000 }
๊ตฌ์กฐ์ฒด๋ ๋ฐ์ดํฐ ๋ชจ์์ "๋ฌถ์ด์" ์ด๋ฆ์ ๋ถ์ด๊ณ ๋จ์ผ ๋จ์๋ก ์ทจ๊ธํ๊ธฐ ์ํด ์กด์ฌํ๋ฏ๋ก, ๊ตฌ์กฐ์ฒด์ ๊ฐ๋ณ ํ๋๋ฅผ ์ถ์ถํ ์ ์๋ ๊ฒ๋ ์ค์ํฉ๋๋ค. ์ด๋ C, Python, Rust ๋๋ JavaScript์์์ฒ๋ผ ์ ํ๊ธฐ๋ฒ(dot notation)์ ์ฌ์ฉํ์ฌ ์ํ๋ฉ๋๋ค.
#eval origin.x0.000000#eval origin.y0.000000
์ด๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์กฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ๋ ํจ์๋ฅผ ์ ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ ์ ๋ง์
์ ๊ธฐ๋ณธ ์ขํ ๊ฐ์ ๋ํ์ฌ ์ํ๋ฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค.
#eval addPoints { x := 1.5, y := 32 } { x := -8, y := 0.2 }
๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
{ x := -6.500000, y := 32.200000 }
ํจ์ ์์ฒด๋ p1๊ณผ p2๋ผ๋ ๋ ๊ฐ์ Point๋ฅผ ์ธ์๋ก ๋ฐ์ต๋๋ค. ๊ฒฐ๊ณผ ์ ์ p1๊ณผ p2์ x ๋ฐ y ํ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํฉ๋๋ค.
def addPoints (p1 : Point) (p2 : Point) : Point := { x := p1.x + p2.x, y := p1.y + p2.y }
๋ง์ฐฌ๊ฐ์ง๋ก, ๋ ์ ์ฌ์ด์ ๊ฑฐ๋ฆฌ, ์ฆ x์ y ์ฑ๋ถ ์ฐจ์ด์ ์ ๊ณฑ์ ํฉ์ ์ ๊ณฑ๊ทผ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
def distance (p1 : Point) (p2 : Point) : Float := Float.sqrt (((p2.x - p1.x) ^ 2.0) + ((p2.y - p1.y) ^ 2.0))
์๋ฅผ ๋ค์ด, (1,2)์ (5,โ1) ์ฌ์ด์ ๊ฑฐ๋ฆฌ๋ 5์
๋๋ค.
#eval distance { x := 1.0, y := 2.0 } { x := 5.0, y := -1.0 }5.000000
์ฌ๋ฌ ๊ตฌ์กฐ์ฒด๊ฐ ๊ฐ์ ์ด๋ฆ์ ํ๋๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. 3์ฐจ์ ์ ๋ฐ์ดํฐ ํ์
์ x์ y ํ๋๋ฅผ ๊ณต์ ํ ์ ์์ผ๋ฉฐ, ๊ฐ์ ํ๋ ์ด๋ฆ์ผ๋ก ์ธ์คํด์คํ๋ ์ ์์ต๋๋ค.
structure Point3D where x : Float y : Float z : Floatdef origin3D : Point3D := { x := 0.0, y := 0.0, z := 0.0 }
์ด๋ ์ค๊ดํธ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ๊ธฐ ์ํด ๊ตฌ์กฐ์ฒด์ ์์ ํ์
์ ์์์ผ ํจ์ ์๋ฏธํฉ๋๋ค. ํ์
์ ์ ์ ์๋ ๊ฒฝ์ฐ Lean์ ๊ตฌ์กฐ์ฒด๋ฅผ ์ธ์คํด์คํํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ด ์ฝ๋๋:
#check { x := 0.0, y := 0.0 }
๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
invalid {...} notation, expected type is not known
๋ณดํต ๊ทธ๋ ๋ฏ์ด, ํ์
๋ช
์๋ฅผ ์ ๊ณตํ์ฌ ์ด ์ํฉ์ ํด๊ฒฐํ ์ ์์ต๋๋ค.
#check ({ x := 0.0, y := 0.0 } : Point){ x := 0.0, y := 0.0 } : Point
ํ๋ก๊ทธ๋จ์ ๋ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค๊ธฐ ์ํด, Lean์ ์ค๊ดํธ ์์ ๊ตฌ์กฐ์ฒด ํ์
๋ช
์๋ฅผ ํ์ฉํ๊ธฐ๋ ํฉ๋๋ค.
#check { x := 0.0, y := 0.0 : Point}{ x := 0.0, y := 0.0 } : Point
1.4.1. ๊ตฌ์กฐ์ฒด ์
๋ฐ์ดํธ
Point์ x ํ๋๋ฅผ 0์ผ๋ก ๋ฐ๊พธ๋ zeroX๋ผ๋ ํจ์๋ฅผ ์์ํด ๋ณด์ธ์. ๋๋ถ๋ถ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด ์ปค๋ฎค๋ํฐ์์ ์ด ๋ฌธ์ฅ์ x๊ฐ ๊ฐ๋ฆฌํค๋ ๋ฉ๋ชจ๋ฆฌ ์์น๋ฅผ ์ ๊ฐ์ผ๋ก ๋ฎ์ด์จ์ผ ํ๋ค๋ ์๋ฏธ์ผ ๊ฒ์
๋๋ค. ํ์ง๋ง Lean์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์
๋๋ค. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ปค๋ฎค๋ํฐ์์ ์ด๋ฐ ์ข
๋ฅ์ ์ง์ ์ ๊ฑฐ์ ํญ์ x ํ๋๋ ์ ๊ฐ์ ๊ฐ๋ฆฌํค๊ณ ๋ค๋ฅธ ๋ชจ๋ ํ๋๋ ์
๋ ฅ์ ์๋ ๊ฐ์ ๊ฐ๋ฆฌํค๋ ์๋ก์ด Point๊ฐ ํ ๋น๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. zeroX๋ฅผ ์์ฑํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ด ์ค๋ช
์ ๋ฌธ์ ๊ทธ๋๋ก ๋ฐ๋ผ, x์ ๋ํ ์ ๊ฐ์ ์ฑ์ฐ๊ณ y๋ฅผ ์๋์ผ๋ก ์ฎ๊ธฐ๋ ๊ฒ์
๋๋ค.
def zeroX (p : Point) : Point := { x := 0, y := p.y }
๊ทธ๋ฌ๋ ์ด ํ๋ก๊ทธ๋๋ฐ ์คํ์ผ์๋ ๋จ์ ์ด ์์ต๋๋ค. ์ฒซ์งธ, ๊ตฌ์กฐ์ฒด์ ์ ํ๋๊ฐ ์ถ๊ฐ๋๋ฉด ์ด๋ค ํ๋๋ ์
๋ฐ์ดํธํ๋ ๋ชจ๋ ๊ณณ์ ์
๋ฐ์ดํธํด์ผ ํ๋ฏ๋ก ์ ์ง ๊ด๋ฆฌ๊ฐ ์ด๋ ค์์ง๋๋ค. ๋์งธ, ๊ตฌ์กฐ์ฒด์ ๊ฐ์ ํ์
์ ํ๋๊ฐ ์ฌ๋ฌ ๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ, ๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ ์ฝ๋ฉ์ผ๋ก ์ธํด ํ๋ ๋ด์ฉ์ด ์ค๋ณต๋๊ฑฐ๋ ๋ฐ๋๋ ์ค์ ์ํ์ด ์์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก, ํ๋ก๊ทธ๋จ์ด ๊ธธ๊ณ ๊ด๋ฃ์ ์ผ๋ก ๋ณํฉ๋๋ค.
Lean์ ๊ตฌ์กฐ์ฒด์ ์ผ๋ถ ํ๋๋ ๋ฐ๊พธ๊ณ ๋๋จธ์ง๋ ๊ทธ๋๋ก ๋๋ ํธ๋ฆฌํ ๊ตฌ๋ฌธ์ ์ ๊ณตํฉ๋๋ค. ์ด๋ ๊ตฌ์กฐ์ฒด ์ด๊ธฐํ์์ with ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฉ๋๋ค. ๋ณ๊ฒฝ๋์ง ์์ ํ๋์ ์์ค๋ with ์์ ์ค๊ณ , ์ ํ๋๋ ๋ค์ ์ต๋๋ค. ์๋ฅผ ๋ค์ด, zeroX๋ ์๋ก์ด x ๊ฐ๋ง์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค.
def zeroX (p : Point) : Point := { p with x := 0 }
์ด ๊ตฌ์กฐ์ฒด ์
๋ฐ์ดํธ ๊ตฌ๋ฌธ์ ๊ธฐ์กด ๊ฐ์ ์์ ํ์ง ์๊ณ , ์ด์ ๊ฐ๊ณผ ์ผ๋ถ ํ๋๋ฅผ ๊ณต์ ํ๋ ์ ๊ฐ์ ์์ฑํ๋ค๋ ์ ์ ๊ธฐ์ตํ์ธ์. fourAndThree๋ผ๋ ์ ์ด ์ฃผ์ด์ก์ ๋:
def fourAndThree : Point := { x := 4.3, y := 3.4 }
์ด๋ฅผ ํ๊ฐํ ๋ค์, zeroX๋ฅผ ์ฌ์ฉํ์ฌ ์
๋ฐ์ดํธํ ๊ฒ์ ํ๊ฐํ๊ณ , ๋ค์ ํ๊ฐํ๋ฉด ์๋ ๊ฐ์ด ๋์ต๋๋ค.
#eval fourAndThree{ x := 4.300000, y := 3.400000 }#eval zeroX fourAndThree{ x := 0.000000, y := 3.400000 }#eval fourAndThree{ x := 4.300000, y := 3.400000 }
๊ตฌ์กฐ์ฒด ์
๋ฐ์ดํธ๊ฐ ์๋ณธ ๊ตฌ์กฐ์ฒด๋ฅผ ์์ ํ์ง ์๋๋ค๋ ์ฌ์ค์ ํ ๊ฐ์ง ๊ฒฐ๊ณผ๋, ์ ๊ฐ์ด ์ด์ ๊ฐ์ผ๋ก๋ถํฐ ๊ณ์ฐ๋๋ ๊ฒฝ์ฐ์ ๋ํด ์ถ๋ก ํ๊ธฐ๊ฐ ๋ ์ฌ์์ง๋ค๋ ๊ฒ์
๋๋ค. ์ด์ ๊ตฌ์กฐ์ฒด์ ๋ํ ๋ชจ๋ ์ฐธ์กฐ๋ ์ ๊ณต๋ ๋ชจ๋ ์ ๊ฐ์์ ๊ณ์ ๋์ผํ ํ๋ ๊ฐ์ ์ฐธ์กฐํฉ๋๋ค.
1.4.2. ๋ด๋ถ ๋์
๋ชจ๋ ๊ตฌ์กฐ์ฒด์๋ ์์ฑ์(constructor)๊ฐ ์์ต๋๋ค. ์ฌ๊ธฐ์ "์์ฑ์"๋ผ๋ ์ฉ์ด๋ ํผ๋์ ์์ธ์ด ๋ ์ ์์ต๋๋ค. Java๋ Python๊ณผ ๊ฐ์ ์ธ์ด์ ์์ฑ์์ ๋ฌ๋ฆฌ, Lean์ ์์ฑ์๋ ๋ฐ์ดํฐ ํ์
์ด ์ด๊ธฐํ๋ ๋ ์คํ๋๋ ์์์ ์ฝ๋๊ฐ ์๋๋๋ค. ๋์ , ์์ฑ์๋ ์๋ก ํ ๋น๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ๋จ์ํ ๋ชจ์ผ๋ ์ญํ ์ ํฉ๋๋ค. ๋ฐ์ดํฐ๋ฅผ ์ ์ฒ๋ฆฌํ๊ฑฐ๋ ์ ํจํ์ง ์์ ์ธ์๋ฅผ ๊ฑฐ๋ถํ๋ ์ฌ์ฉ์ ์ ์ ์์ฑ์๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ "์์ฑ์"๋ผ๋ ๋จ์ด๊ฐ ๋ ๋งฅ๋ฝ์์ ์๋ก ๊ด๋ จ์ ์์ง๋ง ๋ค๋ฅธ ์๋ฏธ๋ฅผ ๊ฐ๋ ๊ฒฝ์ฐ์
๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก, S๋ผ๋ ์ด๋ฆ์ ๊ตฌ์กฐ์ฒด์ ๋ํ ์์ฑ์๋ S.mk๋ผ๋ ์ด๋ฆ์ด ๋ถ์ต๋๋ค. ์ฌ๊ธฐ์ S๋ ๋ค์์คํ์ด์ค ํ์ ์์ด๊ณ , mk๋ ์์ฑ์ ์์ฒด์ ์ด๋ฆ์
๋๋ค. ์ค๊ดํธ ์ด๊ธฐํ ๊ตฌ๋ฌธ ๋์ ์์ฑ์๋ฅผ ์ง์ ์ ์ฉํ ์๋ ์์ต๋๋ค.
#check Point.mk 1.5 2.8
๊ทธ๋ฌ๋ ์ด๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก ์ข์ Lean ์คํ์ผ๋ก ๊ฐ์ฃผ๋์ง ์์ผ๋ฉฐ, Lean์กฐ์ฐจ๋ ํ์ค ๊ตฌ์กฐ์ฒด ์ด๊ธฐํ ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ํผ๋๋ฐฑ์ ๋ฐํํฉ๋๋ค.
{ x := 1.5, y := 2.8 } : Point
์์ฑ์๋ ํจ์ ํ์
์ ๊ฐ์ง๋ฏ๋ก, ํจ์๊ฐ ์์๋๋ ๋ชจ๋ ๊ณณ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Point.mk๋ ๋ ๊ฐ์ Float(๊ฐ๊ฐ x์ y)๋ฅผ ๋ฐ์ ์๋ก์ด Point๋ฅผ ๋ฐํํ๋ ํจ์์
๋๋ค.
#check (Point.mk)Point.mk : Float โ Float โ Point
๊ตฌ์กฐ์ฒด์ ์์ฑ์ ์ด๋ฆ์ ์ฌ์ ์ํ๋ ค๋ฉด, ์ด๋ฆ ์์ ์ฝ๋ก ๋ ๊ฐ๋ฅผ ๋ถ์ฌ ์์ฑํฉ๋๋ค. ์๋ฅผ ๋ค์ด, Point.mk ๋์ Point.point๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ค์๊ณผ ๊ฐ์ด ์์ฑํฉ๋๋ค.
structure Point where point :: x : Float y : Float
์์ฑ์ ์ธ์๋, ๊ตฌ์กฐ์ฒด์ ๊ฐ ํ๋์ ๋ํด ์ ๊ทผ์(accessor) ํจ์๊ฐ ์ ์๋ฉ๋๋ค. ์ด๋ค์ ๊ตฌ์กฐ์ฒด์ ๋ค์์คํ์ด์ค ๋ด์์ ํ๋์ ๋์ผํ ์ด๋ฆ์ ๊ฐ์ง๋๋ค. Point์ ๊ฒฝ์ฐ, ์ ๊ทผ์ ํจ์ Point.x์ Point.y๊ฐ ์์ฑ๋ฉ๋๋ค.
#check (Point.x)Point.x : Point โ Float#check (Point.y)Point.y : Point โ Float
์ฌ์ค, ์ค๊ดํธ ๊ตฌ์กฐ์ฒด ์์ฑ ๊ตฌ๋ฌธ์ด ๋ด๋ถ์ ์ผ๋ก ๊ตฌ์กฐ์ฒด์ ์์ฑ์ ํธ์ถ๋ก ๋ณํ๋๋ ๊ฒ์ฒ๋ผ, ์ด์ addPoints ์ ์์ x ๊ตฌ๋ฌธ์ x ์ ๊ทผ์ ํธ์ถ๋ก ๋ณํ๋ฉ๋๋ค. ์ฆ, #eval origin.x์ #eval Point.x origin์ ๋ชจ๋ ๋ค์์ ์ฐ์ถํฉ๋๋ค.
0.000000
์ ๊ทผ์ ์ ํ๊ธฐ๋ฒ์ ๊ตฌ์กฐ์ฒด ํ๋๋ฟ๋ง ์๋๋ผ ๋ ๋ง์ ๊ฒ๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค. ์์์ ์์ ์ธ์๋ฅผ ๋ฐ๋ ํจ์์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ ์ผ๋ฐ์ ์ผ๋ก, ์ ๊ทผ์ ํ๊ธฐ๋ฒ์ TARGET.f ARG1 ARG2 ... ํ์์ ๊ฐ์ง๋๋ค. TARGET์ ํ์
์ด T์ด๋ฉด, T.f๋ผ๋ ์ด๋ฆ์ ํจ์๊ฐ ํธ์ถ๋ฉ๋๋ค. TARGET์ ํ์
์ด T์ธ ๊ฐ์ฅ ์ผ์ชฝ ์ธ์๊ฐ ๋๋ฉฐ(ํญ์ ์ฒซ ๋ฒ์งธ๋ ์๋), ARG1 ARG2 ...๋ ๋๋จธ์ง ์ธ์๋ก ์์๋๋ก ์ ๊ณต๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, String์ append ํ๋๋ฅผ ๊ฐ์ง ๊ตฌ์กฐ์ฒด๊ฐ ์๋์ง๋ง, ์ ๊ทผ์ ํ๊ธฐ๋ฒ์ผ๋ก ๋ฌธ์์ด์์ String.append๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
#eval "one string".append " and another""one string and another"
์ด ์์์ TARGET์ "one string"์ ๋ํ๋ด๊ณ ARG1์ " and another"๋ฅผ ๋ํ๋
๋๋ค.
Point.modifyBoth ํจ์(์ฆ, Point ๋ค์์คํ์ด์ค์ ์ ์๋ modifyBoth)๋ Point์ ๋ ํ๋ ๋ชจ๋์ ํจ์๋ฅผ ์ ์ฉํฉ๋๋ค.
def Point.modifyBoth (f : Float โ Float) (p : Point) : Point := { x := f p.x, y := f p.y }
Point ์ธ์๊ฐ ํจ์ ์ธ์ ๋ค์ ์ค๋๋ผ๋, ์ ํ๊ธฐ๋ฒ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
#eval fourAndThree.modifyBoth Float.floor{ x := 4.000000, y := 3.000000 }
์ด ๊ฒฝ์ฐ, TARGET์ fourAndThree๋ฅผ ๋ํ๋ด๊ณ , ARG1์ Float.floor์
๋๋ค. ์ด๋ ์ ๊ทผ์ ํ๊ธฐ๋ฒ์ ๋์์ด ๋ฐ๋์ ์ฒซ ๋ฒ์งธ ์ธ์๊ฐ ์๋๋ผ, ํ์
์ด ์ผ์นํ๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
1.4.3. ์ฐ์ต ๋ฌธ์
์ง์ก๋ฉด์ฒด์ ๋์ด, ๋๋น, ๊น์ด๋ฅผ ๊ฐ๊ฐ Float์ผ๋ก ํฌํจํ๋ RectangularPrism์ด๋ผ๋ ์ด๋ฆ์ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํ์ธ์.
์ง์ก๋ฉด์ฒด์ ๋ถํผ๋ฅผ ๊ณ์ฐํ๋ volume : RectangularPrism โ Float๋ผ๋ ์ด๋ฆ์ ํจ์๋ฅผ ์ ์ํ์ธ์.
๋์ ์ผ๋ก ์ ๋ถ์ ๋ํ๋ด๋ Segment๋ผ๋ ์ด๋ฆ์ ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํ๊ณ , ์ ๋ถ์ ๊ธธ์ด๋ฅผ ๊ณ์ฐํ๋ length : Segment โ Float๋ผ๋ ํจ์๋ฅผ ์ ์ํ์ธ์. Segment๋ ์ต๋ ๋ ๊ฐ์ ํ๋๋ฅผ ๊ฐ์ ธ์ผ ํฉ๋๋ค.
RectangularPrism์ ์ ์ธ์ผ๋ก ์ด๋ค ์ด๋ฆ๋ค์ด ๋์
๋๋์?
๋ค์ Hamster์ Book ์ ์ธ์ผ๋ก ์ด๋ค ์ด๋ฆ๋ค์ด ๋์
๋๋์? ๊ทธ๋ค์ ํ์
์ ๋ฌด์์ธ๊ฐ์?
structure Hamster where name : String fluffy : Boolstructure Book where makeBook :: title : String author : String price : Float
1.5. ์๋ฃํ๊ณผ ํจํด
๊ตฌ์กฐ์ฒด๋ ์ฌ๋ฌ ๋
๋ฆฝ์ ์ธ ๋ฐ์ดํฐ๋ฅผ ์กฐํฉํ์ฌ ์๋ก์ด ํ์
์ผ๋ก ํํ๋๋ ์ผ๊ด๋ ์ ์ฒด๋ก ๋ง๋ค ์ ์์ต๋๋ค. ๊ตฌ์กฐ์ฒด์ฒ๋ผ ๊ฐ์ ๋ชจ์์ ๊ทธ๋ฃนํํ๋ ํ์
์ ๊ณฑ ํ์
(product type)์ด๋ผ๊ณ ํฉ๋๋ค. ํ์ง๋ง ๋ง์ ๋๋ฉ์ธ ๊ฐ๋
์ ๊ตฌ์กฐ์ฒด๋ก ์์ฐ์ค๋ฝ๊ฒ ํํ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ด๋ค ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ์ฉ์ ๊ถํ์ ์ถ์ ํด์ผ ํ ์ ์๋๋ฐ, ์ผ๋ถ ์ฌ์ฉ์๋ ๋ฌธ์ ์์ ์์ด๊ณ , ์ผ๋ถ๋ ๋ฌธ์๋ฅผ ํธ์งํ ์ ์์ผ๋ฉฐ, ๋ค๋ฅธ ์ฌ์ฉ์๋ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ ์ ์์ต๋๋ค. ๊ณ์ฐ๊ธฐ์๋ ๋ง์
, ๋บ์
, ๊ณฑ์
๊ณผ ๊ฐ์ ์ฌ๋ฌ ์ดํญ ์ฐ์ฐ์๊ฐ ์์ต๋๋ค. ๊ตฌ์กฐ์ฒด๋ ์ฌ๋ฌ ์ ํ์ง๋ฅผ ์ธ์ฝ๋ฉํ๋ ์ฌ์ด ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ง ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก, ๊ตฌ์กฐ์ฒด๋ ๊ณ ์ ๋ ์์ ํ๋๋ฅผ ์ถ์ ํ๋ ํ๋ฅญํ ๋ฐฉ๋ฒ์ด์ง๋ง, ๋ง์ ์ ํ๋ฆฌ์ผ์ด์
์ ์์์ ์์ ์์๋ฅผ ํฌํจํ ์ ์๋ ๋ฐ์ดํฐ๊ฐ ํ์ํฉ๋๋ค. ํธ๋ฆฌ๋ ๋ฆฌ์คํธ์ ๊ฐ์ ๋๋ถ๋ถ์ ๊ณ ์ ์ ์ธ ์๋ฃ ๊ตฌ์กฐ๋ ์ฌ๊ท์ ์ธ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค. ๋ฆฌ์คํธ์ ๊ผฌ๋ฆฌ๊ฐ ๊ทธ ์์ฒด๋ก ๋ฆฌ์คํธ์ด๊ฑฐ๋, ์ด์ง ํธ๋ฆฌ์ ์ผ์ชฝ๊ณผ ์ค๋ฅธ์ชฝ ๊ฐ์ง๊ฐ ๊ทธ ์์ฒด๋ก ์ด์ง ํธ๋ฆฌ์ธ ๊ฒฝ์ฐ์ฒ๋ผ ๋ง์
๋๋ค. ์์ ์ธ๊ธํ ๊ณ์ฐ๊ธฐ์์ ํํ์ ์์ฒด์ ๊ตฌ์กฐ๊ฐ ์ฌ๊ท์ ์
๋๋ค. ์๋ฅผ ๋ค์ด, ๋ง์
ํํ์์ ํผ๊ฐ์ฐ์๋ ๊ทธ ์์ฒด๊ฐ ๊ณฑ์
ํํ์์ผ ์ ์์ต๋๋ค.
์ ํ์ ํ์ฉํ๋ ์๋ฃํ์ ํฉ ํ์
(sum type)์ด๋ผ๊ณ ํ๊ณ , ์๊ธฐ ์์ ์ ์ธ์คํด์ค๋ฅผ ํฌํจํ ์ ์๋ ์๋ฃํ์ ์ฌ๊ท ์๋ฃํ(recursive datatype)์ด๋ผ๊ณ ํฉ๋๋ค. ์ฌ๊ท์ ์ธ ํฉ ํ์
์ ๊ท๋ฉ์ ์๋ฃํ(inductive datatype)์ด๋ผ๊ณ ๋ถ๋ฆฌ๋๋ฐ, ์ํ์ ๊ท๋ฉ๋ฒ์ ์ฌ์ฉํ์ฌ ์ด์ ๋ํ ๋ช
์ ๋ฅผ ์ฆ๋ช
ํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ํ๋ก๊ทธ๋๋ฐํ ๋, ๊ท๋ฉ์ ์๋ฃํ์ ํจํด ๋งค์นญ๊ณผ ์ฌ๊ท ํจ์๋ฅผ ํตํด ์ฌ์ฉ๋ฉ๋๋ค.
๋ง์ ๋ด์ฅ ํ์
์ ์ฌ์ค ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์๋ ๊ท๋ฉ์ ์๋ฃํ์
๋๋ค. ์๋ฅผ ๋ค์ด, Bool์ ๊ท๋ฉ์ ์๋ฃํ์
๋๋ค.
inductive Bool where | false : Bool | true : Bool
์ด ์ ์๋ ๋ ๊ฐ์ง ์ฃผ์ ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ์ฒซ ๋ฒ์งธ ์ค์ ์๋ก์ด ํ์
์ ์ด๋ฆ(Bool)์ ์ ๊ณตํ๊ณ , ๋๋จธ์ง ์ค๋ค์ ๊ฐ๊ฐ ์์ฑ์(constructor)๋ฅผ ์ค๋ช
ํฉ๋๋ค. ๊ตฌ์กฐ์ฒด์ ์์ฑ์์ ๋ง์ฐฌ๊ฐ์ง๋ก, ๊ท๋ฉ์ ์๋ฃํ์ ์์ฑ์๋ ์์์ ์ด๊ธฐํ ๋ฐ ์ ํจ์ฑ ๊ฒ์ฌ ์ฝ๋๋ฅผ ์ฝ์
ํ๋ ๊ณณ์ด ์๋๋ผ, ๋ค๋ฅธ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ณ ๋ด๋ ๋จ์ํ๊ณ ๋นํ์ฑ์ ์ธ ์ปจํ
์ด๋์ผ ๋ฟ์
๋๋ค. ๊ตฌ์กฐ์ฒด์ ๋ฌ๋ฆฌ, ๊ท๋ฉ์ ์๋ฃํ์ ์ฌ๋ฌ ์์ฑ์๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ true์ false๋ผ๋ ๋ ๊ฐ์ ์์ฑ์๊ฐ ์์ผ๋ฉฐ, ๋ ๋ค ์ธ์๋ฅผ ๋ฐ์ง ์์ต๋๋ค. ๊ตฌ์กฐ์ฒด ์ ์ธ์ด ์ ์ธ๋ ํ์
์ ์ด๋ฆ์ ๋ด ๋ค์์คํ์ด์ค์ ์์ ์ ์ด๋ฆ์ ๋ฃ๋ ๊ฒ์ฒ๋ผ, ๊ท๋ฉ์ ์๋ฃํ๋ ์์ฑ์์ ์ด๋ฆ์ ๋ค์์คํ์ด์ค์ ๋ฃ์ต๋๋ค. Lean ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์๋ true์ false๊ฐ ์ด ๋ค์์คํ์ด์ค์์ ๋ค์ ์ต์คํฌํธ๋์ด Bool.true์ Bool.false๊ฐ ์๋, ๋จ๋
์ผ๋ก ์์ฑ๋ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ ๋ชจ๋ธ๋ง ๊ด์ ์์, ๊ท๋ฉ์ ์๋ฃํ์ ๋ค๋ฅธ ์ธ์ด์์ ๋ด์ธ๋ ์ถ์ ํด๋์ค(sealed abstract class)๊ฐ ์ฌ์ฉ๋ ์ ์๋ ๋ง์ ๋งฅ๋ฝ์์ ์ฌ์ฉ๋ฉ๋๋ค. C#์ด๋ Java์ ๊ฐ์ ์ธ์ด์์๋ Bool์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ฌํ๊ฒ ์ ์ํ ์ ์์ต๋๋ค.
abstract class Bool {}class True extends Bool {}class False extends Bool {}
ํ์ง๋ง, ์ด๋ฌํ ํํ์ ๊ตฌ์ฒด์ ์ธ ๋ด์ฉ์ ์๋นํ ๋ค๋ฆ
๋๋ค. ํนํ, ๊ฐ๊ฐ์ ๋น์ถ์ ํด๋์ค๋ ์๋ก์ด ํ์
๊ณผ ๋ฐ์ดํฐ๋ฅผ ํ ๋นํ๋ ์๋ก์ด ๋ฐฉ๋ฒ์ ๋ชจ๋ ๋ง๋ญ๋๋ค. ๊ฐ์ฒด ์งํฅ ์์ ์์ True์ False๋ ๋ชจ๋ Bool๋ณด๋ค ๋ ๊ตฌ์ฒด์ ์ธ ํ์
์ธ ๋ฐ๋ฉด, Lean ์ ์๋ Bool์ด๋ผ๋ ์๋ก์ด ํ์
๋ง ๋์
ํฉ๋๋ค.
์์ด ์๋ ์ ์ ํ์
์ธ Nat์ ๊ท๋ฉ์ ์๋ฃํ์
๋๋ค.
inductive Nat where | zero : Nat | succ (n : Nat) : Nat
์ฌ๊ธฐ์ zero๋ 0์ ๋ํ๋ด๊ณ , succ๋ ๋ค๋ฅธ ์ด๋ค ์์ ๋ค์ ์(successor)๋ฅผ ๋ํ๋
๋๋ค. succ์ ์ ์ธ์ ์ธ๊ธ๋ Nat์ ๋ฐ๋ก ์ ์๋๊ณ ์๋ Nat ํ์
๊ทธ ์์ฒด์
๋๋ค. ๋ค์ ์๋ "1 ๋ ํฐ ์"๋ฅผ ์๋ฏธํ๋ฏ๋ก, 5์ ๋ค์ ์๋ 6์ด๊ณ 32,185์ ๋ค์ ์๋ 32,186์
๋๋ค. ์ด ์ ์๋ฅผ ์ฌ์ฉํ๋ฉด, 4๋ Nat.succ (Nat.succ (Nat.succ (Nat.succ Nat.zero)))๋ก ํํ๋ฉ๋๋ค. ์ด ์ ์๋ ์ด๋ฆ์ด ์ฝ๊ฐ ๋ค๋ฅธ ๊ฒ์ ์ ์ธํ๋ฉด Bool์ ์ ์์ ๊ฑฐ์ ๊ฐ์ต๋๋ค. ์ ์ผํ ์ค์ง์ ์ธ ์ฐจ์ด์ ์ succ ๋ค์ (n : Nat)๊ฐ ์จ๋ค๋ ๊ฒ์ธ๋ฐ, ์ด๋ succ ์์ฑ์๊ฐ n์ด๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง Nat ํ์
์ ์ธ์๋ฅผ ๋ฐ๋๋ค๋ ๊ฒ์ ๋ช
์ํฉ๋๋ค. zero์ succ๋ผ๋ ์ด๋ฆ์ ๊ทธ๋ค์ ํ์
์ ๋ด ๋ค์์คํ์ด์ค์ ์์ผ๋ฏ๋ก, ๊ฐ๊ฐ Nat.zero์ Nat.succ๋ก ์ฐธ์กฐ๋์ด์ผ ํฉ๋๋ค.
n๊ณผ ๊ฐ์ ์ธ์ ์ด๋ฆ์ Lean์ ์ค๋ฅ ๋ฉ์์ง๋ ์ํ์ ์ฆ๋ช
์ ์์ฑํ ๋ ์ ๊ณต๋๋ ํผ๋๋ฐฑ์ ๋ํ๋ ์ ์์ต๋๋ค. Lean์๋ ์ด๋ฆ์ผ๋ก ์ธ์๋ฅผ ์ ๊ณตํ๋ ์ ํ์ ๊ตฌ๋ฌธ๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ฐ์ ์ผ๋ก ์ธ์ ์ด๋ฆ์ ์ ํ์ ๊ตฌ์กฐ์ฒด ํ๋ ์ด๋ฆ์ ์ ํ๋ณด๋ค ๋ ์ค์ํ๋ฐ, API์ ํฐ ๋ถ๋ถ์ ์ฐจ์งํ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค.
C# ์ด๋ Java์์ Nat์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ ์ ์์ต๋๋ค.
abstract class Nat {}class Zero extends Nat {}class Succ extends Nat { public Nat n; public Succ(Nat pred) { n = pred; }}
์์ Bool ์์ ์์์ฒ๋ผ, ์ด๋ Lean์ ๋ฑ๊ฐ๋ฌผ๋ณด๋ค ๋ ๋ง์ ํ์
์ ์ ์ํฉ๋๋ค. ๋ํ, ์ด ์์ ๋ Lean ์๋ฃํ ์์ฑ์๊ฐ C# ์ด๋ Java์ ์์ฑ์๋ผ๊ธฐ๋ณด๋ค๋ ์ถ์ ํด๋์ค์ ์๋ธํด๋์ค์ ํจ์ฌ ๋ ์ ์ฌํ๋ค๋ ์ ์ ๊ฐ์กฐํฉ๋๋ค. ์ฌ๊ธฐ์ ํ์๋ ์์ฑ์๋ ์คํ๋ ์ด๊ธฐํ ์ฝ๋๋ฅผ ํฌํจํ๊ณ ์๊ธฐ ๋๋ฌธ์
๋๋ค.
ํฉ ํ์
์ TypeScript์์ ๊ตฌ๋ณ๋ ์ ๋์จ(discriminated union)์ ์ธ์ฝ๋ฉํ๊ธฐ ์ํด ๋ฌธ์์ด ํ๊ทธ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๊ณผ๋ ์ ์ฌํฉ๋๋ค. TypeScript์์ Nat์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ ์ ์์ต๋๋ค.
interface Zero { tag: "zero";}interface Succ { tag: "succ"; predecessor: Nat;}type Nat = Zero | Succ;
C# ๋ฐ Java์ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ด ์ธ์ฝ๋ฉ์ Lean์์๋ณด๋ค ๋ ๋ง์ ํ์
์ ๊ฐ์ง๊ฒ ๋๋๋ฐ, Zero์ Succ๊ฐ ๊ฐ๊ฐ ๋
๋ฆฝ์ ์ธ ํ์
์ด๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ํ ์ด๋ Lean ์์ฑ์๊ฐ ๋ด์ฉ๋ฌผ์ ์๋ณํ๋ ํ๊ทธ๋ฅผ ํฌํจํ๋ JavaScript๋ TypeScript์ ๊ฐ์ฒด์ ํด๋นํ๋ค๋ ๊ฒ์ ๋ณด์ฌ์ค๋๋ค.
1.5.1. ํจํด ๋งค์นญ
๋ง์ ์ธ์ด์์ ์ด๋ฌํ ์ข
๋ฅ์ ๋ฐ์ดํฐ๋ ๋จผ์ ์ธ์คํด์ค-์ค๋ธ(instance-of) ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ค ์๋ธํด๋์ค๋ฅผ ๋ฐ์๋์ง ํ์ธํ ๋ค์, ํด๋น ์๋ธํด๋์ค์์ ์ฌ์ฉ ๊ฐ๋ฅํ ํ๋์ ๊ฐ์ ์ฝ๋ ๋ฐฉ์์ผ๋ก ์๋น๋ฉ๋๋ค. ์ธ์คํด์ค-์ค๋ธ ํ์ธ์ ์ด๋ค ์ฝ๋๋ฅผ ์คํํ ์ง ๊ฒฐ์ ํ์ฌ ์ด ์ฝ๋์ ํ์ํ ๋ฐ์ดํฐ๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก ๋ณด์ฅํ๋ ๋ฐ๋ฉด, ํ๋ ์์ฒด๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. Lean์์๋ ์ด ๋ ๊ฐ์ง ๋ชฉ์ ์ด ๋ชจ๋ ํจํด ๋งค์นญ์ ์ํด ๋์์ ์ํ๋ฉ๋๋ค.
ํจํด ๋งค์นญ์ ์ฌ์ฉํ๋ ํจ์์ ์๋ isZero๋ก, ์ด ํจ์๋ ์ธ์๊ฐ Nat.zero์ผ ๋ true๋ฅผ, ๊ทธ๋ ์ง ์์ผ๋ฉด false๋ฅผ ๋ฐํํฉ๋๋ค.
def isZero (n : Nat) : Bool := match n with | Nat.zero => true | Nat.succ k => false
match ํํ์์๋ ํจ์์ ์ธ์ n์ด ๊ตฌ์กฐ ๋ถํด๋ฅผ ์ํด ์ ๊ณต๋ฉ๋๋ค. ๋ง์ฝ n์ด Nat.zero์ ์ํด ์์ฑ๋์๋ค๋ฉด, ํจํด ๋งค์นญ์ ์ฒซ ๋ฒ์งธ ๋ถ๊ธฐ๊ฐ ์ ํ๋์ด ๊ฒฐ๊ณผ๋ true๊ฐ ๋ฉ๋๋ค. ๋ง์ฝ n์ด Nat.succ์ ์ํด ์์ฑ๋์๋ค๋ฉด, ๋ ๋ฒ์งธ ๋ถ๊ธฐ๊ฐ ์ ํ๋์ด ๊ฒฐ๊ณผ๋ false๊ฐ ๋ฉ๋๋ค.
๋จ๊ณ๋ณ๋ก, isZero Nat.zero์ ํ๊ฐ๋ ๋ค์๊ณผ ๊ฐ์ด ์งํ๋ฉ๋๋ค.
isZero Nat.zero
โ
โโนโ
โ\implies
match Nat.zero with
โ
โโนโ
โ\implies
| Nat.zero => true
โ
โโนโ
โ\implies
| Nat.succ k => false
โ
โโนโ
โ\implies
true
isZero 5์ ํ๊ฐ๋ ๋น์ทํ๊ฒ ์งํ๋ฉ๋๋ค.
isZero 5
โ
โโนโ
โ\implies
isZero (Nat.succ (Nat.succ (Nat.succ (Nat.succ (Nat.succ Nat.zero)))))
โ
โโนโ
โ\implies
match Nat.succ (Nat.succ (Nat.succ (Nat.succ (Nat.succ Nat.zero)))) with| Nat.zero => true| Nat.succ k => false
โ
โโนโ
โ\implies
false
isZero์ ํจํด ๋ ๋ฒ์งธ ๋ถ๊ธฐ์ ์๋ k๋ ์ฅ์์ด ์๋๋๋ค. ์ด๋ Nat.succ์ ์ธ์์ธ Nat์ ์ ๊ณต๋ ์ด๋ฆ์ผ๋ก ๋ณด์ด๊ฒ ๋ง๋ญ๋๋ค. ๊ทธ๋ฌ๋ฉด ๊ทธ ๋ ์์ ์ซ์๋ฅผ ์ฌ์ฉํ์ฌ ํํ์์ ์ต์ข
๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํ ์ ์์ต๋๋ค.
์ด๋ค ์ซ์ n์ ๋ค์ ์๊ฐ n๋ณด๋ค 1 ํฐ ์(์ฆ, n+1)์ธ ๊ฒ์ฒ๋ผ, ์ด๋ค ์์ ์ด์ ์(predecessor)๋ ๊ทธ ์๋ณด๋ค 1 ์์ ์์
๋๋ค. ๋ง์ฝ pred๊ฐ Nat์ ์ด์ ์๋ฅผ ์ฐพ๋ ํจ์๋ผ๋ฉด, ๋ค์ ์์ ๋ค์ ์์๋ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ์์ผ ํฉ๋๋ค.
#eval pred 54#eval pred 839838
Nat์ ์์๋ฅผ ํํํ ์ ์๊ธฐ ๋๋ฌธ์, Nat.zero๋ ์ฝ๊ฐ์ ๋์ ์
๋๋ค. ๋ณดํต Nat์ผ๋ก ์์
ํ ๋, ์์๋ฅผ ์์ฑํ ์ ์๋ ์ฐ์ฐ์๋ค์ 0 ์์ฒด๋ฅผ ์์ฑํ๋๋ก ์ฌ์ ์๋ฉ๋๋ค.
#eval pred 00
Nat์ ์ด์ ์๋ฅผ ์ฐพ๊ธฐ ์ํด, ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ์ด๋ค ์์ฑ์๊ฐ ๊ทธ๊ฒ์ ๋ง๋๋ ๋ฐ ์ฌ์ฉ๋์๋์ง ํ์ธํ๋ ๊ฒ์
๋๋ค. ๋ง์ฝ Nat.zero์๋ค๋ฉด, ๊ฒฐ๊ณผ๋ Nat.zero์
๋๋ค. ๋ง์ฝ Nat.succ์๋ค๋ฉด, k๋ผ๋ ์ด๋ฆ์ด ๊ทธ ์๋์ Nat์ ์ฐธ์กฐํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด Nat์ด ์ํ๋ ์ด์ ์์ด๋ฏ๋ก, Nat.succ ๋ถ๊ธฐ์ ๊ฒฐ๊ณผ๋ k์
๋๋ค.
def pred (n : Nat) : Nat := match n with | Nat.zero => Nat.zero | Nat.succ k => k
์ด ํจ์๋ฅผ 5์ ์ ์ฉํ๋ฉด ๋ค์ ๋จ๊ณ๋ค์ด ๋์ต๋๋ค.
pred 5
โ
โโนโ
โ\implies
pred (Nat.succ 4)
โ
โโนโ
โ\implies
match Nat.succ 4 with| Nat.zero => Nat.zero| Nat.succ k => k
โ
โโนโ
โ\implies
4
ํจํด ๋งค์นญ์ ํฉ ํ์
๋ฟ๋ง ์๋๋ผ ๊ตฌ์กฐ์ฒด์๋ ํจ๊ป ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Point3D์์ ์ธ ๋ฒ์งธ ์ฐจ์์ ์ถ์ถํ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
def depth (p : Point3D) : Float := match p with | { x:= h, y := w, z := d } => d
์ด ๊ฒฝ์ฐ, Point3D.z ์ ๊ทผ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํจ์ฌ ๊ฐ๋จํ๊ฒ ์ง๋ง, ๊ตฌ์กฐ์ฒด ํจํด์ ๋๋๋ก ํจ์๋ฅผ ์์ฑํ๋ ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด ๋ ์ ์์ต๋๋ค.
1.5.2. ์ฌ๊ท ํจ์
์ ์๋๊ณ ์๋ ์ด๋ฆ์ ์ฐธ์กฐํ๋ ์ ์๋ฅผ ์ฌ๊ท ์ ์(recursive definition)๋ผ๊ณ ํฉ๋๋ค. ๊ท๋ฉ์ ์๋ฃํ์ ์ฌ๊ท์ ์ผ ์ ์์ต๋๋ค. ์ค์ ๋ก, Nat์ succ๊ฐ ๋ ๋ค๋ฅธ Nat์ ์๊ตฌํ๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฌํ ์๋ฃํ์ ์์
๋๋ค. ์ฌ๊ท ์๋ฃํ์ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฉ๋ชจ๋ฆฌ์ ๊ฐ์ ๊ธฐ์ ์ ์์ธ์ ์ํด์๋ง ์ ํ๋๋, ์์๋ก ํฐ ๋ฐ์ดํฐ๋ฅผ ๋ํ๋ผ ์ ์์ต๋๋ค. ์๋ฃํ ์ ์์์ ๊ฐ ์์ฐ์์ ๋ํด ํ๋์ ์์ฑ์๋ฅผ ๋ชจ๋ ์ ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ ๊ฒ์ฒ๋ผ, ๊ฐ ๊ฐ๋ฅ์ฑ์ ๋ํ ํจํด ๋งค์นญ ์ผ์ด์ค๋ฅผ ๋ชจ๋ ์ ๋ ๊ฒ๋ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
์ฌ๊ท ์๋ฃํ์ ์ฌ๊ท ํจ์์ ์ ์ด์ธ๋ฆฝ๋๋ค. Nat์ ๋ํ ๊ฐ๋จํ ์ฌ๊ท ํจ์๋ ์ธ์๊ฐ ์ง์์ธ์ง ํ์ธํ๋ ๊ฒ์
๋๋ค. ์ด ๊ฒฝ์ฐ, Nat.zero๋ ์ง์์
๋๋ค. ์ด์ ๊ฐ์ ์ฝ๋์ ๋น์ฌ๊ท์ ์ธ ๋ถ๊ธฐ๋ฅผ ๋ฒ ์ด์ค ์ผ์ด์ค(base case)๋ผ๊ณ ํฉ๋๋ค. ํ์์ ๋ค์ ์๋ ์ง์์ด๊ณ , ์ง์์ ๋ค์ ์๋ ํ์์
๋๋ค. ์ด๋ Nat.succ๋ก ๋ง๋ค์ด์ง ์ซ์๊ฐ ์ง์๋ผ๋ ๊ฒ์ ๊ทธ ์ธ์๊ฐ ์ง์๊ฐ ์๋ ๋์ ๊ฐ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
def even (n : Nat) : Bool := match n with | Nat.zero => true | Nat.succ k => not (even k)
์ด๋ฌํ ์ฌ๊ณ ํจํด์ Nat์ ๋ํ ์ฌ๊ท ํจ์๋ฅผ ์์ฑํ ๋ ์ ํ์ ์
๋๋ค. ๋จผ์ , Nat.zero์ ๋ํด ๋ฌด์์ ํ ์ง ์๋ณํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์, ์์์ Nat์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ ๋ค์ ์์ ๋ํ ๊ฒฐ๊ณผ๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ๊ณ , ์ด ๋ณํ์ ์ฌ๊ท ํธ์ถ์ ๊ฒฐ๊ณผ์ ์ ์ฉํฉ๋๋ค. ์ด ํจํด์ ๊ตฌ์กฐ์ ์ฌ๊ท(structural recursion)๋ผ๊ณ ํฉ๋๋ค.
๋ง์ ์ธ์ด์ ๋ฌ๋ฆฌ, Lean์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ์ฌ๊ท ํจ์๊ฐ ๊ฒฐ๊ตญ ๋ฒ ์ด์ค ์ผ์ด์ค์ ๋๋ฌํ๋๋ก ๋ณด์ฅํฉ๋๋ค. ํ๋ก๊ทธ๋๋ฐ ๊ด์ ์์ ์ด๋ ์ฐ๋ฐ์ ์ธ ๋ฌดํ ๋ฃจํ๋ฅผ ๋ฐฐ์ ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด ๊ธฐ๋ฅ์ ์ ๋ฆฌ๋ฅผ ์ฆ๋ช
ํ ๋ ํนํ ์ค์ํ๋ฐ, ๋ฌดํ ๋ฃจํ๋ ํฐ ์ด๋ ค์์ ์ผ๊ธฐํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด๋ก ์ธํ ๊ฒฐ๊ณผ ์ค ํ๋๋ Lean์ด ์๋ ์ซ์์ ๋ํด ์ฌ๊ท์ ์ผ๋ก ์์ ์ ํธ์ถํ๋ ค๋ even ๋ฒ์ ์ ๋ฐ์๋ค์ด์ง ์๋๋ค๋ ๊ฒ์
๋๋ค.
def evenLoops (n : Nat) : Bool := match n with | Nat.zero => true | Nat.succ k => not (evenLoops n)
์ค๋ฅ ๋ฉ์์ง์ ์ค์ํ ๋ถ๋ถ์ Lean์ด ์ฌ๊ท ํจ์๊ฐ ํญ์ ๋ฒ ์ด์ค ์ผ์ด์ค์ ๋๋ฌํ๋ค๋ ๊ฒ์ ๊ฒฐ์ ํ ์ ์์๋ค๋ ๊ฒ์
๋๋ค(์ค์ ๋ก ๊ทธ๋ ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค).
fail to show termination for evenLoopswith errorsfailed to infer structural recursion:Not considering parameter n of evenLoops: it is unchanged in the recursive callsno parameters suitable for structural recursionwell-founded recursion cannot be used, `evenLoops` does not take any (non-fixed) arguments
๋ง์
์ ๋ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ์ง๋ง, ๊ทธ ์ค ํ๋๋ง ๊ฒ์ฌํ๋ฉด ๋ฉ๋๋ค. ์ซ์ n์ 0์ ๋ํ๋ ค๋ฉด, ๊ทธ๋ฅ n์ ๋ฐํํ๋ฉด ๋ฉ๋๋ค. k์ ๋ค์ ์๋ฅผ n์ ๋ํ๋ ค๋ฉด, k๋ฅผ n์ ๋ํ ๊ฒฐ๊ณผ์ ๋ค์ ์๋ฅผ ์ทจํ๋ฉด ๋ฉ๋๋ค.
def plus (n : Nat) (k : Nat) : Nat := match k with | Nat.zero => n | Nat.succ k' => Nat.succ (plus n k')
plus์ ์ ์์์, k'๋ผ๋ ์ด๋ฆ์ ์ธ์ k์ ์ฐ๊ฒฐ๋์ด ์์ง๋ง ๋์ผํ์ง๋ ์๋ค๋ ๊ฒ์ ๋ํ๋ด๊ธฐ ์ํด ์ ํ๋์์ต๋๋ค. ์๋ฅผ ๋ค์ด, plus 3 2์ ํ๊ฐ๋ฅผ ๋ฐ๋ผ๊ฐ ๋ณด๋ฉด ๋ค์ ๋จ๊ณ๋ค์ด ๋์ต๋๋ค.
plus 3 2
โ
โโนโ
โ\implies
plus 3 (Nat.succ (Nat.succ Nat.zero))
โ
โโนโ
โ\implies
match Nat.succ (Nat.succ Nat.zero) with| Nat.zero => 3| Nat.succ k' => Nat.succ (plus 3 k')
โ
โโนโ
โ\implies
Nat.succ (plus 3 (Nat.succ Nat.zero))
โ
โโนโ
โ\implies
Nat.succ (match Nat.succ Nat.zero with| Nat.zero => 3| Nat.succ k' => Nat.succ (plus 3 k'))
โ
โโนโ
โ\implies
Nat.succ (Nat.succ (plus 3 Nat.zero))
โ
โโนโ
โ\implies
Nat.succ (Nat.succ (match Nat.zero with| Nat.zero => 3| Nat.succ k' => Nat.succ (plus 3 k')))
โ
โโนโ
โ\implies
Nat.succ (Nat.succ 3)
โ
โโนโ
โ\implies
5
๋ง์
์ ๋ํด ์๊ฐํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ n+kn+k๊ฐ Nat.succ๋ฅผ n์ k๋ฒ ์ ์ฉํ๋ ๊ฒ์ด๋ผ๋ ์ ์
๋๋ค. ๋น์ทํ๊ฒ, ๊ณฑ์
nรkn\times k๋ n์ ์์ ์๊ฒ k๋ฒ ๋ํ๋ ๊ฒ์ด๊ณ , ๋บ์
nโknโk๋ n์ ์ด์ ์๋ฅผ k๋ฒ ์ทจํ๋ ๊ฒ์
๋๋ค.
def times (n : Nat) (k : Nat) : Nat := match k with | Nat.zero => Nat.zero | Nat.succ k' => plus n (times n k')def minus (n : Nat) (k : Nat) : Nat := match k with | Nat.zero => n | Nat.succ k' => pred (minus n k')
๋ชจ๋ ํจ์๊ฐ ๊ตฌ์กฐ์ ์ฌ๊ท๋ฅผ ์ฌ์ฉํ์ฌ ์ฝ๊ฒ ์์ฑ๋ ์ ์๋ ๊ฒ์ ์๋๋๋ค. ๋ง์
์ ๋ฐ๋ณต๋ Nat.succ๋ก, ๊ณฑ์
์ ๋ฐ๋ณต๋ ๋ง์
์ผ๋ก, ๋บ์
์ ๋ฐ๋ณต๋ ์ด์ ์๋ก ์ดํดํ๋ ๊ฒ์ ๋๋์
์ ๋ฐ๋ณต๋ ๋บ์
์ผ๋ก ๊ตฌํํ ์ ์์์ ์์ฌํฉ๋๋ค. ์ด ๊ฒฝ์ฐ, ํผ์ ์๊ฐ ์ ์๋ณด๋ค ์์ผ๋ฉด ๊ฒฐ๊ณผ๋ 0์
๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด, ๊ฒฐ๊ณผ๋ ํผ์ ์์์ ์ ์๋ฅผ ๋บ ๊ฐ์ ์ ์๋ก ๋๋ ๊ฐ์ ๋ค์ ์์
๋๋ค.
def div (n : Nat) (k : Nat) : Nat := if n < k then 0 else Nat.succ (div (n - k) k)
๋ ๋ฒ์งธ ์ธ์๊ฐ 0์ด ์๋ ํ, ์ด ํ๋ก๊ทธ๋จ์ ํญ์ ๋ฒ ์ด์ค ์ผ์ด์ค๋ฅผ ํฅํด ์งํํ๋ฏ๋ก ์ข
๋ฃ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ ๊ตฌ์กฐ์ ์ผ๋ก ์ฌ๊ท์ ์ด์ง ์์๋ฐ, 0์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ๊ณ ๋ ์์ Nat์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ ๋ค์ ์์ ๋ํ ๊ฒฐ๊ณผ๋ก ๋ณํํ๋ ํจํด์ ๋ฐ๋ฅด์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค. ํนํ, ํจ์์ ์ฌ๊ท์ ํธ์ถ์ด ์
๋ ฅ ์์ฑ์์ ์ธ์๊ฐ ์๋ ๋ค๋ฅธ ํจ์ ํธ์ถ์ ๊ฒฐ๊ณผ์ ์ ์ฉ๋ฉ๋๋ค. ๋ฐ๋ผ์ Lean์ ๋ค์ ๋ฉ์์ง์ ํจ๊ป ์ด๋ฅผ ๊ฑฐ๋ถํฉ๋๋ค.
fail to show termination for divwith errorsfailed to infer structural recursion:Not considering parameter k of div: it is unchanged in the recursive callsCannot use parameter k: failed to eliminate recursive application div (n - k) kfailed to prove termination, possible solutions: - Use `have`-expressions to prove the remaining goals - Use `termination_by` to specify a different well-founded relation - Use `decreasing_by` to specify your own tactic for discharging this kind of goalk n:Nathโ:ยฌn < kโข n - k < n
์ด ๋ฉ์์ง๋ div๊ฐ ์๋์ผ๋ก ์ข
๋ฃ ์ฆ๋ช
์ ์๊ตฌํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์ด ์ฃผ์ ๋ ๋ง์ง๋ง ์ฅ์์ ํ๊ตฌ๋ฉ๋๋ค.
1.6. ๋คํ์ฑ(Polymorphism)
๋๋ถ๋ถ์ ์ธ์ด์์์ฒ๋ผ, Lean์์๋ ํ์
์ ์ธ์๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, List Nat ํ์
์ ์์ฐ์์ ๋ฆฌ์คํธ๋ฅผ, List String์ ๋ฌธ์์ด์ ๋ฆฌ์คํธ๋ฅผ, ๊ทธ๋ฆฌ๊ณ List (List Point)๋ Point๋ก ์ด๋ฃจ์ด์ง ๋ฆฌ์คํธ๋ก ์ด๋ฃจ์ด์ง ๋ฆฌ์คํธ๋ฅผ ๋ํ๋
๋๋ค. ์ด๋ C#์ด๋ Java ๊ฐ์ ์ธ์ด์ List<Nat>, List<String>, ๋๋ List<List<Point>>์ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. Lean์ด ํจ์์ ์ธ์๋ฅผ ์ ๋ฌํ ๋ ๊ณต๋ฐฑ์ ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ, ํ์
์ ์ธ์๋ฅผ ์ ๋ฌํ ๋๋ ๊ณต๋ฐฑ์ ์ฌ์ฉํฉ๋๋ค.
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ๋คํ์ฑ์ด๋ผ๋ ์ฉ์ด๋ ์ผ๋ฐ์ ์ผ๋ก ํ์
์ ์ธ์๋ก ๋ฐ๋ ๋ฐ์ดํฐ ํ์
๊ณผ ์ ์๋ฅผ ๊ฐ๋ฆฌํต๋๋ค. ์ด๋ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ ์ปค๋ฎค๋ํฐ์์ ์ผ๋ฐ์ ์ผ๋ก ์ํผํด๋์ค์ ์ผ๋ถ ๋์์ ์ฌ์ ์(override)ํ ์ ์๋ ์๋ธํด๋์ค๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฒ๊ณผ๋ ๋ค๋ฆ
๋๋ค. ์ด ์ฑ
์์ "๋คํ์ฑ"์ ํญ์ ์ ์์ ์๋ฏธ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฌํ ํ์
์ธ์๋ค์ ๋ฐ์ดํฐ ํ์
์ด๋ ์ ์ ๋ด์์ ์ฌ์ฉ๋ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋์ผํ ๋ฐ์ดํฐ ํ์
์ด๋ ์ ์๋ฅผ ์ธ์์ ์ด๋ฆ์ ๋ค๋ฅธ ํ์
์ผ๋ก ๋์ฒดํ์ฌ ์ป์ด์ง๋ ๋ชจ๋ ํ์
๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
Point ๊ตฌ์กฐ์ฒด๋ x์ y ํ๋๊ฐ ๋ชจ๋ Float์ด์ด์ผ ํฉ๋๋ค. ํ์ง๋ง ์ ์ ๋ํด ๊ฐ ์ขํ์ ํน์ ํํ์ ์๊ตฌํ๋ ๋ณธ์ง์ ์ธ ์ด์ ๋ ์์ต๋๋ค. Point์ ๋คํ์ ๋ฒ์ ์ธ PPoint๋ ํ์
์ ์ธ์๋ก ๋ฐ์ ๋ ํ๋์ ๋ชจ๋ ๊ทธ ํ์
์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
structure PPoint (ฮฑ : Type) where x : ฮฑ y : ฮฑ
ํจ์ ์ ์์ ์ธ์๋ค์ด ์ ์๋๋ ์ด๋ฆ ๋ฐ๋ก ๋ค์ ์ฐ์ด๋ ๊ฒ์ฒ๋ผ, ๊ตฌ์กฐ์ฒด์ ์ธ์๋ค๋ ๊ตฌ์กฐ์ฒด ์ด๋ฆ ๋ฐ๋ก ๋ค์ ์ฐ์
๋๋ค. Lean์์๋ ๋ ๊ตฌ์ฒด์ ์ธ ์ด๋ฆ์ด ๋ ์ค๋ฅด์ง ์์ ๋ ํ์
์ธ์์ ์ด๋ฆ์ผ๋ก ๊ทธ๋ฆฌ์ค ๋ฌธ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ด๋ก์
๋๋ค. Type์ ๋ค๋ฅธ ํ์
์ ์ค๋ช
ํ๋ ํ์
์ด๋ฏ๋ก, Nat, List String, PPoint Int๋ ๋ชจ๋ Type์ด๋ผ๋ ํ์
์ ๊ฐ์ง๋๋ค.
List์ ๋ง์ฐฌ๊ฐ์ง๋ก, PPoint๋ ํน์ ํ์
์ ์ธ์๋ก ์ ๊ณตํ์ฌ ์ฌ์ฉํ ์ ์์ต๋๋ค.
def natOrigin : PPoint Nat := { x := Nat.zero, y := Nat.zero }
์ด ์์ ์์๋ ๋ ํ๋ ๋ชจ๋ Nat ํ์
์ผ ๊ฒ์ผ๋ก ์์๋ฉ๋๋ค. ํจ์๊ฐ ์ธ์ ๋ณ์๋ฅผ ์ธ์ ๊ฐ์ผ๋ก ๋์ฒดํ์ฌ ํธ์ถ๋๋ ๊ฒ์ฒ๋ผ, PPoint์ Nat ํ์
์ ์ธ์๋ก ์ ๊ณตํ๋ฉด x์ y ํ๋๊ฐ Nat ํ์
์ ๊ฐ๋ ๊ตฌ์กฐ์ฒด๊ฐ ์์ฑ๋ฉ๋๋ค. ์ด๋ ์ธ์ ์ด๋ฆ ฮฑ๊ฐ ์ธ์ ํ์
Nat์ผ๋ก ๋์ฒด๋์๊ธฐ ๋๋ฌธ์
๋๋ค. Lean์์ ํ์
์ ์ผ๋ฐ์ ์ธ ํํ์์ด๋ฏ๋ก, PPoint์ ๊ฐ์ ๋คํ์ ํ์
์ ์ธ์๋ฅผ ์ ๋ฌํ๋ ๋ฐ ํน๋ณํ ๋ฌธ๋ฒ์ด ํ์ํ์ง ์์ต๋๋ค.
์ ์ ๋ํ ํ์
์ ์ธ์๋ก ๋ฐ์ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋คํ์ ์ด ๋ฉ๋๋ค. replaceX ํจ์๋ PPoint์ x ํ๋๋ฅผ ์๋ก์ด ๊ฐ์ผ๋ก ๋์ฒดํฉ๋๋ค. replaceX๊ฐ ๋ชจ๋ ๋คํ์ Point์ ๋ํด ์๋ํ๋๋ก ํ๋ ค๋ฉด, ํจ์ ์์ฒด๊ฐ ๋คํ์ ์ด์ด์ผ ํฉ๋๋ค. ์ด๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ฅผ ์ ํ๋์ ํ์
์ผ๋ก ํ๊ณ , ์ดํ์ ์ธ์๋ค์ด ์ฒซ ๋ฒ์งธ ์ธ์์ ์ด๋ฆ์ ์ฐธ์กฐํ๋๋ก ํจ์ผ๋ก์จ ๋ฌ์ฑ๋ฉ๋๋ค.
def replaceX (ฮฑ : Type) (point : PPoint ฮฑ) (newX : ฮฑ) : PPoint ฮฑ := { point with x := newX }
์ฆ, ์ธ์ point์ newX์ ํ์
์ด ฮฑ๋ฅผ ์ธ๊ธํ ๋, ์ด๋ ์ฒซ ๋ฒ์งธ ์ธ์๋ก ์ ๊ณต๋ ํ์
์ ์ฐธ์กฐํ๋ ๊ฒ์
๋๋ค. ์ด๋ ํจ์ ์ธ์ ์ด๋ฆ์ด ํจ์ ๋ณธ๋ฌธ์์ ์ฌ์ฉ๋ ๋ ์ ๊ณต๋ ๊ฐ์ ์ฐธ์กฐํ๋ ๋ฐฉ์๊ณผ ์ ์ฌํฉ๋๋ค.
์ด๋ Lean์๊ฒ replaceX์ ํ์
์ ํ์ธํ๋๋ก ์์ฒญํ ๋ค์, replaceX Nat์ ํ์
์ ํ์ธํ๋๋ก ์์ฒญํจ์ผ๋ก์จ ๋ณผ ์ ์์ต๋๋ค.
#check (replaceX)replaceX : (ฮฑ : Type) โ PPoint ฮฑ โ ฮฑ โ PPoint ฮฑ
์ด ํจ์ ํ์
์ ์ฒซ ๋ฒ์งธ ์ธ์์ ์ด๋ฆ์ ํฌํจํ๋ฉฐ, ํ์
๋ด์ ์ดํ ์ธ์๋ค์ ์ด ์ด๋ฆ์ ๋ค์ ์ฐธ์กฐํฉ๋๋ค. ํจ์ ์ ์ฉ์ ๊ฐ์ด ํจ์ ๋ณธ๋ฌธ์์ ์ธ์ ์ด๋ฆ์ ์ ๊ณต๋ ์ธ์ ๊ฐ์ผ๋ก ๋์ฒดํ์ฌ ์ฐพ์์ง๋ ๊ฒ์ฒ๋ผ, ํจ์ ์ ์ฉ์ ํ์
์ ํจ์์ ๋ฐํ ํ์
์์ ์ธ์ ์ด๋ฆ์ ์ ๊ณต๋ ๊ฐ์ผ๋ก ๋์ฒดํ์ฌ ์ฐพ์์ง๋๋ค. ์ฒซ ๋ฒ์งธ ์ธ์์ธ Nat์ ์ ๊ณตํ๋ฉด, ํ์
์ ๋๋จธ์ง ๋ถ๋ถ์ ์๋ ๋ชจ๋ ฮฑ๊ฐ Nat์ผ๋ก ๋์ฒด๋ฉ๋๋ค.
#check replaceX NatreplaceX Nat : PPoint Nat โ Nat โ PPoint Nat
๋๋จธ์ง ์ธ์๋ค์ ๋ช
์์ ์ผ๋ก ์ด๋ฆ์ด ์ง์ ๋์ง ์์๊ธฐ ๋๋ฌธ์, ๋ ๋ง์ ์ธ์๊ฐ ์ ๊ณต๋์ด๋ ์ถ๊ฐ์ ์ธ ์นํ์ ๋ฐ์ํ์ง ์์ต๋๋ค.
#check replaceX Nat natOriginreplaceX Nat natOrigin : Nat โ PPoint Nat#check replaceX Nat natOrigin 5replaceX Nat natOrigin 5 : PPoint Nat
์ ์ฒด ํจ์ ์ ์ฉ ํํ์์ ํ์
์ด ํ์
์ ์ธ์๋ก ์ ๋ฌํจ์ผ๋ก์จ ๊ฒฐ์ ๋์๋ค๋ ์ฌ์ค์ ๊ทธ๊ฒ์ ํ๊ฐํ๋ ๋ฅ๋ ฅ์ ์๋ฌด๋ฐ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
#eval replaceX Nat natOrigin 5{ x := 5, y := 0 }
๋คํ์ ํจ์๋ ์ด๋ฆ์ด ์ง์ ๋ ํ์
์ธ์๋ฅผ ๋ฐ๊ณ , ์ดํ์ ํ์
๋ค์ด ๊ทธ ์ธ์์ ์ด๋ฆ์ ์ฐธ์กฐํจ์ผ๋ก์จ ์๋ํฉ๋๋ค. ํ์ง๋ง ํ์
์ธ์๋ง์ด ์ด๋ฆ์ ๊ฐ์ง ์ ์๋ ํน๋ณํ ๊ฒ์ ์๋๋๋ค. ์์ ๋๋ ์์ ๋ถํธ๋ฅผ ๋ํ๋ด๋ ๋ฐ์ดํฐ ํ์
์ ๊ฐ์ ํด ๋ด
์๋ค.
inductive Sign where | pos | neg
์ธ์๊ฐ ๋ถํธ์ธ ํจ์๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. ์ธ์๊ฐ ์์์ด๋ฉด ํจ์๋ Nat์ ๋ฐํํ๊ณ , ์์์ด๋ฉด Int๋ฅผ ๋ฐํํฉ๋๋ค.
def posOrNegThree (s : Sign) : match s with | Sign.pos => Nat | Sign.neg => Int := match s with | Sign.pos => (3 : Nat) | Sign.neg => (-3 : Int)
ํ์
์ ์ผ๊ธ ๊ฐ์ฒด์ด๋ฉฐ Lean ์ธ์ด์ ์ผ๋ฐ์ ์ธ ๊ท์น์ ์ฌ์ฉํ์ฌ ๊ณ์ฐ๋ ์ ์์ผ๋ฏ๋ก, ๋ฐ์ดํฐ ํ์
์ ๋ํ ํจํด ๋งค์นญ์ ํตํด ๊ณ์ฐ๋ ์ ์์ต๋๋ค. Lean์ด ์ด ํจ์๋ฅผ ํ์ธํ ๋, ํจ์ ๋ณธ๋ฌธ์ match ํํ์์ด ํ์
์ match ํํ์๊ณผ ์ผ์นํ๋ค๋ ์ฌ์ค์ ์ด์ฉํ์ฌ pos ์ผ์ด์ค์ ์์ ํ์
์ Nat์ผ๋ก, neg ์ผ์ด์ค์ ์์ ํ์
์ Int๋ก ๋ง๋ญ๋๋ค.
posOrNegThree๋ฅผ pos์ ์ ์ฉํ๋ฉด ํจ์ ๋ณธ๋ฌธ๊ณผ ๋ฐํ ํ์
๋ชจ๋์์ ์ธ์ ์ด๋ฆ s๊ฐ pos๋ก ๋์ฒด๋ฉ๋๋ค. ํ๊ฐ๋ ํํ์๊ณผ ๊ทธ ํ์
๋ชจ๋์์ ๋ฐ์ํ ์ ์์ต๋๋ค.
(posOrNegThree Sign.pos : match Sign.pos with | Sign.pos => Nat | Sign.neg => Int)
โ
โโนโ
โ\implies
((match Sign.pos with | Sign.pos => (3 : Nat) | Sign.neg => (-3 : Int)) : match Sign.pos with | Sign.pos => Nat | Sign.neg => Int)
โ
โโนโ
โ\implies
((3 : Nat) : Nat)
โ
โโนโ
โ\implies
3
1.6.1. ์ฐ๊ฒฐ ๋ฆฌ์คํธ(Linked Lists)
Lean์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ List๋ผ๋ ํ์ค์ ์ธ ์ฐ๊ฒฐ ๋ฆฌ์คํธ ๋ฐ์ดํฐ ํ์
๊ณผ ์ด๋ฅผ ๋ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์๋ ํน๋ณํ ๋ฌธ๋ฒ์ด ํฌํจ๋์ด ์์ต๋๋ค. ๋ฆฌ์คํธ๋ ๋๊ดํธ ์์ ์์ฑ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, 10 ๋ฏธ๋ง์ ์์๋ฅผ ํฌํจํ๋ ๋ฆฌ์คํธ๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
def primesUnder10 : List Nat := [2, 3, 5, 7]
๋ด๋ถ์ ์ผ๋ก List๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ ๊ท๋ฉ์ ๋ฐ์ดํฐ ํ์
์
๋๋ค.
inductive List (ฮฑ : Type) where | nil : List ฮฑ | cons : ฮฑ โ List ฮฑ โ List ฮฑ
ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ค์ ์ ์๋ ์์ง ์๊ฐ๋์ง ์์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์ฝ๊ฐ ๋ค๋ฅด์ง๋ง, ๋ณธ์ง์ ์ผ๋ก๋ ์ ์ฌํฉ๋๋ค. ์ด ์ ์๋ List๊ฐ PPoint์ฒ๋ผ ๋จ์ผ ํ์
์ ์ธ์๋ก ๋ฐ๋๋ค๊ณ ๋งํฉ๋๋ค. ์ด ํ์
์ ๋ฆฌ์คํธ์ ์ ์ฅ๋ ํญ๋ชฉ์ ํ์
์
๋๋ค. ์์ฑ์์ ๋ฐ๋ฅด๋ฉด, List ฮฑ๋ nil ๋๋ cons๋ก ๋ง๋ค์ด์ง ์ ์์ต๋๋ค. nil ์์ฑ์๋ ๋น ๋ฆฌ์คํธ๋ฅผ ๋ํ๋ด๊ณ , cons ์์ฑ์๋ ๋น์ด์์ง ์์ ๋ฆฌ์คํธ์ ์ฌ์ฉ๋ฉ๋๋ค. cons์ ์ฒซ ๋ฒ์งธ ์ธ์๋ ๋ฆฌ์คํธ์ head์ด๊ณ , ๋ ๋ฒ์งธ ์ธ์๋ tail์
๋๋ค. nn๊ฐ์ ํญ๋ชฉ์ ํฌํจํ๋ ๋ฆฌ์คํธ๋ nn๊ฐ์ cons ์์ฑ์๋ฅผ ํฌํจํ๋ฉฐ, ๋ง์ง๋ง cons๋ nil์ ๊ผฌ๋ฆฌ๋ก ๊ฐ์ง๋๋ค.
primesUnder10 ์์ ๋ List์ ์์ฑ์๋ฅผ ์ง์ ์ฌ์ฉํ์ฌ ๋ ๋ช
์์ ์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค.
def explicitPrimesUnder10 : List Nat := List.cons 2 (List.cons 3 (List.cons 5 (List.cons 7 List.nil)))
์ด ๋ ์ ์๋ ์์ ํ ๋์ผํ์ง๋ง, primesUnder10์ด explicitPrimesUnder10๋ณด๋ค ํจ์ฌ ์ฝ๊ธฐ ์ฝ์ต๋๋ค.
List๋ฅผ ์๋นํ๋ ํจ์๋ Nat์ ์๋นํ๋ ํจ์์ ๊ฑฐ์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ ์๋ ์ ์์ต๋๋ค. ์ค์ ๋ก, ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๊ฐ succ ์์ฑ์์์ ์ถ๊ฐ ๋ฐ์ดํฐ ํ๋๊ฐ ๋งค๋ฌ๋ ค ์๋ Nat์ผ๋ก ์๊ฐํ ์ ์์ต๋๋ค. ์ด ๊ด์ ์์ ๋ฆฌ์คํธ์ ๊ธธ์ด๋ฅผ ๊ณ์ฐํ๋ ๊ณผ์ ์ ๊ฐ cons๋ฅผ succ๋ก, ๋ง์ง๋ง nil์ 0์ผ๋ก ๋ฐ๊พธ๋ ๊ณผ์ ์
๋๋ค. replaceX๊ฐ ์ ํ๋์ ํ์
์ ์ธ์๋ก ๋ฐ์๋ ๊ฒ์ฒ๋ผ, length๋ ๋ฆฌ์คํธ ํญ๋ชฉ์ ํ์
์ ์ธ์๋ก ๋ฐ์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฆฌ์คํธ๊ฐ ๋ฌธ์์ด์ ํฌํจํ๋ค๋ฉด ์ฒซ ๋ฒ์งธ ์ธ์๋ String์
๋๋ค: length String ["Sourdough", "bread"]. ์ด๋ ๋ค์๊ณผ ๊ฐ์ด ๊ณ์ฐ๋์ด์ผ ํฉ๋๋ค.
length String ["Sourdough", "bread"]
โ
โโนโ
โ\implies
length String (List.cons "Sourdough" (List.cons "bread" List.nil))
โ
โโนโ
โ\implies
Nat.succ (length String (List.cons "bread" List.nil))
โ
โโนโ
โ\implies
Nat.succ (Nat.succ (length String List.nil))
โ
โโนโ
โ\implies
Nat.succ (Nat.succ Nat.zero)
โ
โโนโ
โ\implies
2
length์ ์ ์๋ ๋ฆฌ์คํธ ํญ๋ชฉ ํ์
์ ์ธ์๋ก ๋ฐ๊ธฐ ๋๋ฌธ์ ๋คํ์ ์ด๋ฉด์ ์์ ์ ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์ ์ฌ๊ท์ ์
๋๋ค. ์ผ๋ฐ์ ์ผ๋ก ํจ์๋ ๋ฐ์ดํฐ์ ํํ๋ฅผ ๋ฐ๋ฆ
๋๋ค. ์ฌ๊ท์ ๋ฐ์ดํฐ ํ์
์ ์ฌ๊ท ํจ์๋ก ์ด์ด์ง๊ณ , ๋คํ์ ๋ฐ์ดํฐ ํ์
์ ๋คํ์ ํจ์๋ก ์ด์ด์ง๋๋ค.
def length (ฮฑ : Type) (xs : List ฮฑ) : Nat := match xs with | List.nil => Nat.zero | List.cons y ys => Nat.succ (length ฮฑ ys)
xs์ ys์ ๊ฐ์ ์ด๋ฆ์ ๊ด๋ก์ ์ผ๋ก ์ ์ ์๋ ๊ฐ๋ค์ ๋ฆฌ์คํธ๋ฅผ ๋ํ๋ด๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฆ์ s๋ ๋ณต์ํ์์ ๋ํ๋ด๋ฏ๋ก, "x s"์ "y s"๊ฐ ์๋ "์์์ฆ(exes)"์ "์์ด์ฆ(whys)"๋ก ๋ฐ์๋ฉ๋๋ค.
๋ฆฌ์คํธ์ ๋ํ ํจ์๋ฅผ ๋ ์ฝ๊ฒ ์ฝ์ ์ ์๋๋ก, ๋๊ดํธ ํ๊ธฐ๋ฒ []์ ์ฌ์ฉํ์ฌ nil์ ๋ํด ํจํด ๋งค์นญํ ์ ์๊ณ , cons ๋์ ์ค์(infix) ์ฐ์ฐ์ ::๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
def length (ฮฑ : Type) (xs : List ฮฑ) : Nat := match xs with | [] => 0 | y :: ys => Nat.succ (length ฮฑ ys)
1.6.2. ์์์ ์ธ์(Implicit Arguments)
replaceX์ length๋ ๋ชจ๋ ์ฌ์ฉํ๊ธฐ์ ๋ค์ ๋ฒ๊ฑฐ๋ก์ด๋ฐ, ์๋ํ๋ฉด ํ์
์ธ์๋ ๋ณดํต ์ดํ์ ๊ฐ๋ค์ ์ํด ์ ์ผํ๊ฒ ๊ฒฐ์ ๋๊ธฐ ๋๋ฌธ์
๋๋ค. ์ค์ ๋ก ๋๋ถ๋ถ์ ์ธ์ด์์ ์ปดํ์ผ๋ฌ๋ ํ์
์ธ์๋ฅผ ์ค์ค๋ก ์๋ฒฝํ๊ฒ ๊ฒฐ์ ํ ์ ์์ผ๋ฉฐ, ์ฌ์ฉ์๋ก๋ถํฐ ๊ฐ๋์ฉ๋ง ๋์์ด ํ์ํฉ๋๋ค. ์ด๋ Lean์์๋ ๋ง์ฐฌ๊ฐ์ง์
๋๋ค. ํจ์๋ฅผ ์ ์ํ ๋ ์ธ์๋ฅผ ๊ดํธ ๋์ ์ค๊ดํธ๋ก ๊ฐ์ธ์ ์์์ ์ผ๋ก ์ ์ธํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์์์ ํ์
์ธ์๋ฅผ ๊ฐ์ง replaceX ๋ฒ์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def replaceX {ฮฑ : Type} (point : PPoint ฮฑ) (newX : ฮฑ) : PPoint ฮฑ := { point with x := newX }
Lean์ด ์ดํ์ ์ธ์๋ค๋ก๋ถํฐ ฮฑ์ ๊ฐ์ ์ถ๋ก ํ ์ ์๊ธฐ ๋๋ฌธ์, Nat์ ๋ช
์์ ์ผ๋ก ์ ๊ณตํ์ง ์๊ณ ๋ natOrigin๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์์ต๋๋ค.
#eval replaceX natOrigin 5{ x := 5, y := 0 }
๋ง์ฐฌ๊ฐ์ง๋ก, length๋ ํญ๋ชฉ ํ์
์ ์์์ ์ผ๋ก ๋ฐ๋๋ก ์ฌ์ ์ํ ์ ์์ต๋๋ค.
def length {ฮฑ : Type} (xs : List ฮฑ) : Nat := match xs with | [] => 0 | y :: ys => Nat.succ (length ys)
์ด length ํจ์๋ primesUnder10์ ์ง์ ์ ์ฉ๋ ์ ์์ต๋๋ค.
#eval length primesUnder104
ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ Lean์ ์ด ํจ์๋ฅผ List.length๋ผ๊ณ ๋ถ๋ฅด๋๋ฐ, ์ด๋ ๊ตฌ์กฐ์ฒด ํ๋ ์ ๊ทผ์ ์ฌ์ฉ๋๋ ์ (dot) ๋ฌธ๋ฒ์ด ๋ฆฌ์คํธ์ ๊ธธ์ด๋ฅผ ์ฐพ๋ ๋ฐ์๋ ์ฌ์ฉ๋ ์ ์์์ ์๋ฏธํฉ๋๋ค.
#eval primesUnder10.length4
C# ๊ณผ Java๊ฐ ๋๋๋ก ํ์
์ธ์๋ฅผ ๋ช
์์ ์ผ๋ก ์ ๊ณตํด์ผ ํ๋ ๊ฒ์ฒ๋ผ, Lean๋ ํญ์ ์์์ ์ธ์๋ฅผ ์ฐพ์ ์ ์๋ ๊ฒ์ ์๋๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ, ์ธ์ ์ด๋ฆ์ ์ฌ์ฉํ์ฌ ์ ๊ณตํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ ์ ๋ฆฌ์คํธ์๋ง ์๋ํ๋ List.length ๋ฒ์ ์ ฮฑ๋ฅผ Int๋ก ์ค์ ํ์ฌ ์ง์ ํ ์ ์์ต๋๋ค.
#check List.length (ฮฑ := Int)List.length : List Int โ Nat
1.6.3. ๋ ๋ง์ ๋ด์ฅ ๋ฐ์ดํฐ ํ์
Lean์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ ๋ฆฌ์คํธ ์ธ์๋ ๋ค์ํ ๋งฅ๋ฝ์์ ์ฌ์ฉํ ์ ์๋ ์ฌ๋ฌ ๋ค๋ฅธ ๊ตฌ์กฐ์ฒด์ ๊ท๋ฉ์ ๋ฐ์ดํฐ ํ์
์ด ํฌํจ๋์ด ์์ต๋๋ค.
1.6.3.1. Option
๋ชจ๋ ๋ฆฌ์คํธ์ ์ฒซ ๋ฒ์งธ ํญ๋ชฉ์ด ์๋ ๊ฒ์ ์๋๋๋ค. ์ด๋ค ๋ฆฌ์คํธ๋ ๋น์ด ์์ต๋๋ค. ์ปฌ๋ ์
์ ๋ํ ๋ง์ ์ฐ์ฐ์ ์ฐพ๊ณ ์๋ ๊ฒ์ ์ฐพ์ง ๋ชปํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฆฌ์คํธ์์ ์ฒซ ๋ฒ์งธ ํญ๋ชฉ์ ์ฐพ๋ ํจ์๋ ๊ทธ๋ฌํ ํญ๋ชฉ์ ์ฐพ์ง ๋ชปํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ฒซ ๋ฒ์งธ ํญ๋ชฉ์ด ์์์์ ์๋ฆฌ๋ ๋ฐฉ๋ฒ์ด ์์ด์ผ ํฉ๋๋ค.
๋ง์ ์ธ์ด์๋ ๊ฐ์ ๋ถ์ฌ๋ฅผ ๋ํ๋ด๋ null ๊ฐ์ด ์์ต๋๋ค. Lean์ ๊ธฐ์กด ํ์
์ ํน๋ณํ null ๊ฐ์ ๋ถ์ฌํ๋ ๋์ , Option์ด๋ผ๋ ๋ฐ์ดํฐ ํ์
์ ์ ๊ณตํ์ฌ ๋ค๋ฅธ ํ์
์ ๋๋ฝ๋ ๊ฐ์ ๋ํ๋ด๋ ํ์์๋ฅผ ๋ถ์ฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ ํ์ฉ Int๋ Option Int๋ก ํํ๋๊ณ , ๋ ํ์ฉ ๋ฌธ์์ด ๋ฆฌ์คํธ๋ Option (List String) ํ์
์ผ๋ก ํํ๋ฉ๋๋ค. ๋ ํ์ฉ์ฑ์ ๋ํ๋ด๊ธฐ ์ํด ์๋ก์ด ํ์
์ ๋์
ํ๋ค๋ ๊ฒ์, Option Int๊ฐ Int๊ฐ ์์๋๋ ๋งฅ๋ฝ์์ ์ฌ์ฉ๋ ์ ์๊ธฐ ๋๋ฌธ์ ํ์
์์คํ
์ด null ๊ฒ์ฌ๋ฅผ ์์ง ์๋๋ก ๋ณด์ฅํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
Option์๋ some๊ณผ none์ด๋ผ๋ ๋ ๊ฐ์ ์์ฑ์๊ฐ ์์ผ๋ฉฐ, ๊ฐ๊ฐ ๊ธฐ๋ณธ ํ์
์ ๋์ด ์๋ ๋ฒ์ ๊ณผ ๋ ๋ฒ์ ์ ๋ํ๋
๋๋ค. ๋์ด ์๋ ์์ฑ์์ธ some์ ๊ธฐ๋ณธ ๊ฐ์ ํฌํจํ๊ณ , none์ ์ธ์๋ฅผ ๋ฐ์ง ์์ต๋๋ค:
inductive Option (ฮฑ : Type) : Type where | none : Option ฮฑ | some (val : ฮฑ) : Option ฮฑ
Option ํ์
์ C#์ด๋ Kotlin๊ณผ ๊ฐ์ ์ธ์ด์ ๋ ํ์ฉ ํ์
๊ณผ ๋งค์ฐ ์ ์ฌํ์ง๋ง, ๋์ผํ์ง๋ ์์ต๋๋ค. ์ด๋ค ์ธ์ด์์๋ ๋ง์ฝ ์ด๋ค ํ์
(์: Boolean)์ด ํญ์ ํด๋น ํ์
์ ์ค์ ๊ฐ(true์ false)์ ์ฐธ์กฐํ๋ค๋ฉด, Boolean? ๋๋ Nullable<Boolean> ํ์
์ ์ถ๊ฐ์ ์ผ๋ก null ๊ฐ์ ํ์ฉํฉ๋๋ค. ์ด๋ฅผ ํ์
์์คํ
์์ ์ถ์ ํ๋ ๊ฒ์ ๋งค์ฐ ์ ์ฉํฉ๋๋ค. ํ์
๊ฒ์ฌ๊ธฐ์ ๋ค๋ฅธ ๋๊ตฌ๋ค์ ํ๋ก๊ทธ๋๋จธ๊ฐ null ๊ฒ์ฌ๋ฅผ ๊ธฐ์ตํ๋๋ก ๋์ธ ์ ์๊ณ , ํ์
์๊ทธ๋์ฒ๋ฅผ ํตํด ๋ ํ์ฉ์ฑ์ ๋ช
์์ ์ผ๋ก ์ค๋ช
ํ๋ API๋ ๊ทธ๋ ์ง ์์ ๊ฒ๋ณด๋ค ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ฌํ ๋ ํ์ฉ ํ์
์ Lean์ Option๊ณผ ํ ๊ฐ์ง ๋งค์ฐ ์ค์ํ ์ ์์ ๋ค๋ฆ
๋๋ค. ๋ฐ๋ก ์ฌ๋ฌ ๊ณ์ธต์ ์ ํ์ฑ์ ํ์ฉํ์ง ์๋๋ค๋ ์ ์
๋๋ค. Option (Option Int)๋ none, some none, ๋๋ some (some 360)์ผ๋ก ๊ตฌ์ฑ๋ ์ ์์ต๋๋ค. ๋ฐ๋ฉด์ Kotlin์ T??๋ฅผ T?์ ๋์ผํ๊ฒ ์ทจ๊ธํฉ๋๋ค. ์ด ๋ฏธ๋ฌํ ์ฐจ์ด๋ ์ค์ ๋ก๋ ๊ฑฐ์ ๊ด๋ จ์ด ์์ง๋ง, ๋๋๋ก ์ค์ํ ์ ์์ต๋๋ค.
๋ฆฌ์คํธ์ ์ฒซ ๋ฒ์งธ ํญ๋ชฉ์ (์กด์ฌํ๋ค๋ฉด) ์ฐพ์ผ๋ ค๋ฉด List.head?๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ฌผ์ํ๋ ์ด๋ฆ์ ์ผ๋ถ์ด๋ฉฐ, C#์ด๋ Kotlin์์ ๋ ํ์ฉ ํ์
์ ๋ํ๋ด๋ ๋ฐ ์ฌ์ฉ๋๋ ๋ฌผ์ํ์๋ ๊ด๋ จ์ด ์์ต๋๋ค. List.head?์ ์ ์์์ ๋ฐ์ค์ ๋ฆฌ์คํธ์ ๋๋จธ์ง ๋ถ๋ถ์ ๋ํ๋ด๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ํจํด์์ ๋ฐ์ค์ ๋ฌด์์ด๋ ์ผ์น์ํค์ง๋ง, ์ผ์น๋ ๋ฐ์ดํฐ๋ฅผ ์ฐธ์กฐํ๊ธฐ ์ํ ๋ณ์๋ฅผ ๋์
ํ์ง๋ ์์ต๋๋ค. ์ด๋ฆ ๋์ ๋ฐ์ค์ ์ฌ์ฉํ๋ ๊ฒ์ ์
๋ ฅ์ ์ผ๋ถ๊ฐ ๋ฌด์๋๋ค๋ ๊ฒ์ ๋
์์๊ฒ ๋ช
ํํ๊ฒ ์ ๋ฌํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
def List.head? {ฮฑ : Type} (xs : List ฮฑ) : Option ฮฑ := match xs with | [] => none | y :: _ => some y
Lean์ ๋ช
๋ช
๊ท์น์ ์คํจํ ์ ์๋ ์ฐ์ฐ์ ์ ๋ฏธ์ฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ทธ๋ฃน์ผ๋ก ์ ์ํ๋ ๊ฒ์
๋๋ค. ?๋ Option์ ๋ฐํํ๋ ๋ฒ์ ์, !๋ ์ ํจํ์ง ์์ ์
๋ ฅ์ ์ ๊ณตํ์ ๋ ์ถฉ๋ํ๋ ๋ฒ์ ์, D๋ ์ฐ์ฐ์ด ์คํจํ ๊ฒฝ์ฐ ๊ธฐ๋ณธ๊ฐ์ ๋ฐํํ๋ ๋ฒ์ ์ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ํจํด์ ๋ฐ๋ผ, List.head๋ ํธ์ถ์๊ฐ ๋ฆฌ์คํธ๊ฐ ๋น์ด ์์ง ์๋ค๋ ์ํ์ ์ฆ๊ฑฐ๋ฅผ ์ ๊ณตํ๋๋ก ์๊ตฌํ๊ณ , List.head?๋ Option์ ๋ฐํํ๋ฉฐ, List.head!๋ ๋น ๋ฆฌ์คํธ๋ฅผ ์ ๋ฌ๋ฐ์ผ๋ฉด ํ๋ก๊ทธ๋จ์ ์ถฉ๋์ํค๊ณ , List.headD๋ ๋ฆฌ์คํธ๊ฐ ๋น์ด ์์ ๊ฒฝ์ฐ ๋ฐํํ ๊ธฐ๋ณธ๊ฐ์ ๋ฐ์ต๋๋ค. ๋ฌผ์ํ์ ๋๋ํ๋ ํน๋ณํ ๊ตฌ๋ฌธ์ด ์๋๋ผ ์ด๋ฆ์ ์ผ๋ถ์ธ๋ฐ, ์ด๋ Lean์ ๋ช
๋ช
๊ท์น์ด ๋ง์ ์ธ์ด๋ณด๋ค ๋ ์์ ๋กญ๊ธฐ ๋๋ฌธ์
๋๋ค.
head?๋ List ๋ค์์คํ์ด์ค์ ์ ์๋์ด ์์ผ๋ฏ๋ก, ์ ๊ทผ์ ํ๊ธฐ๋ฒ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค:
#eval primesUnder10.head?some 2
๊ทธ๋ฌ๋ ๋น ๋ฆฌ์คํธ์ ๋ํด ํ
์คํธํ๋ ค๊ณ ํ๋ฉด ๋ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค:
#eval [].head?don't know how to synthesize implicit argument `ฮฑ` @List.nil ?m.3context:โข Type ?u.71735don't know how to synthesize implicit argument `ฮฑ` @_root_.List.head? ?m.3 []context:โข Type ?u.71735
์ด๋ Lean์ด ํํ์์ ํ์
์ ์์ ํ ๊ฒฐ์ ํ ์ ์์๊ธฐ ๋๋ฌธ์
๋๋ค. ํนํ, List.head?์ ๋ํ ์์์ ํ์
์ธ์์ List.nil์ ๋ํ ์์์ ํ์
์ธ์๋ฅผ ๋ชจ๋ ์ฐพ์ง ๋ชปํ์ต๋๋ค. Lean์ ์ถ๋ ฅ์์ ?m.XYZ๋ ์ถ๋ก ํ ์ ์์๋ ํ๋ก๊ทธ๋จ์ ์ผ๋ถ๋ฅผ ๋ํ๋
๋๋ค. ์ด๋ฌํ ์ ์ ์๋ ๋ถ๋ถ์ ๋ฉํ๋ณ์๋ผ๊ณ ํ๋ฉฐ, ์ผ๋ถ ์ค๋ฅ ๋ฉ์์ง์ ๋ํ๋ฉ๋๋ค. ํํ์์ ํ๊ฐํ๊ธฐ ์ํด Lean์ ๊ทธ ํ์
์ ์ฐพ์ ์ ์์ด์ผ ํ๋๋ฐ, ๋น ๋ฆฌ์คํธ์๋ ํ์
์ ์ฐพ์ ์ ์๋ ํญ๋ชฉ์ด ์๊ธฐ ๋๋ฌธ์ ํ์
์ ์ฌ์ฉํ ์ ์์์ต๋๋ค. ๋ช
์์ ์ผ๋ก ํ์
์ ์ ๊ณตํ๋ฉด Lean์ด ์งํํ ์ ์์ต๋๋ค:
#eval [].head? (ฮฑ := Int)none
ํ์
์ ํ์
์ฃผ์์ผ๋ก๋ ์ ๊ณต๋ ์ ์์ต๋๋ค:
#eval ([] : List Int).head?none
์ค๋ฅ ๋ฉ์์ง๋ ์ ์ฉํ ๋จ์๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ ๋ฉ์์ง ๋ชจ๋ ๋๋ฝ๋ ์์์ ์ธ์๋ฅผ ์ค๋ช
ํ๊ธฐ ์ํด ๋์ผํ ๋ฉํ๋ณ์๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ด๋ Lean์ด ํด๊ฒฐ์ฑ
์ ์ค์ ๊ฐ์ ๊ฒฐ์ ํ ์๋ ์์์ง๋ง ๋ ๋๋ฝ๋ ๋ถ๋ถ์ด ๋์ผํ ํด๊ฒฐ์ฑ
์ ๊ณต์ ํ ๊ฒ์ด๋ผ๊ณ ๊ฒฐ์ ํ์์ ์๋ฏธํฉ๋๋ค.
1.6.3.2. Prod
"Product"์ ์ฝ์์ธ Prod ๊ตฌ์กฐ์ฒด๋ ๋ ๊ฐ์ ํจ๊ป ๋ฌถ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, Prod Nat String์ Nat๊ณผ String์ ํฌํจํฉ๋๋ค. ์ฆ, PPoint Nat์ Prod Nat Nat์ผ๋ก ๋์ฒด๋ ์ ์์ต๋๋ค. Prod๋ C#์ ํํ, Kotlin์ Pair ๋ฐ Triple ํ์
, C++์ tuple๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ๋ง์ ์ ํ๋ฆฌ์ผ์ด์
์์๋ Point์ ๊ฐ์ ๊ฐ๋จํ ๊ฒฝ์ฐ์๋ ์์ฒด ๊ตฌ์กฐ์ฒด๋ฅผ ์ ์ํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค. ์๋ํ๋ฉด ๋๋ฉ์ธ ์ฉ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ํ, ๊ตฌ์กฐ์ฒด ํ์
์ ์ ์ํ๋ฉด ๋ค๋ฅธ ๋๋ฉ์ธ ๊ฐ๋
์ ๋ค๋ฅธ ํ์
์ ํ ๋นํ์ฌ ์๋ก ์์ด๋ ๊ฒ์ ๋ฐฉ์งํจ์ผ๋ก์จ ๋ ๋ง์ ์ค๋ฅ๋ฅผ ์ก๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋ฐ๋ฉด์, ์๋ก์ด ํ์
์ ์ ์ํ๋ ์ค๋ฒํค๋๊ฐ ๊ฐ์น๊ฐ ์๋ ๊ฒฝ์ฐ๋ ์์ต๋๋ค. ๋ํ, ์ผ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ "์"๋ณด๋ค ๋ ๊ตฌ์ฒด์ ์ธ ๊ฐ๋
์ด ์์ ์ ๋๋ก ์ถฉ๋ถํ ์ผ๋ฐ์ ์
๋๋ค. ๋ง์ง๋ง์ผ๋ก, ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์๋ ๋ด์ฅ๋ ์ ํ์
์ ๋ ์ฝ๊ฒ ๋ค๋ฃฐ ์ ์๊ฒ ํด์ฃผ๋ ๋ค์ํ ํธ์ ํจ์๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
Prod ๊ตฌ์กฐ์ฒด๋ ๋ ๊ฐ์ ํ์
์ธ์๋ก ์ ์๋ฉ๋๋ค:
structure Prod (ฮฑ : Type) (ฮฒ : Type) : Type where fst : ฮฑ snd : ฮฒ
๋ฆฌ์คํธ๋ ๋งค์ฐ ์์ฃผ ์ฌ์ฉ๋๋ฏ๋ก ๊ฐ๋
์ฑ์ ๋์ด๊ธฐ ์ํ ํน๋ณํ ๊ตฌ๋ฌธ์ด ์์ต๋๋ค. ๊ฐ์ ์ด์ ๋ก, ํ๋ก๋ํธ ํ์
๊ณผ ๊ทธ ์์ฑ์ ๋ชจ๋ ํน๋ณํ ๊ตฌ๋ฌธ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. Prod ฮฑ ฮฒ ํ์
์ ์ผ๋ฐ์ ์ผ๋ก ฮฑ ร ฮฒ๋ก ์ฐ์ด๋ฉฐ, ์ด๋ ์งํฉ์ ๋ฐ์นด๋ฅดํธ ๊ณฑ์ ๋ํ ์ผ๋ฐ์ ์ธ ํ๊ธฐ๋ฒ์ ๋ฐ์ํฉ๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก, ์์ ๋ํ ์ผ๋ฐ์ ์ธ ์ํ์ ํ๊ธฐ๋ฒ์ Prod์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฆ, ๋ค์๊ณผ ๊ฐ์ด ์ฐ๋ ๋์ ์:
def fives : String ร Int := { fst := "five", snd := 5 }
๋ค์๊ณผ ๊ฐ์ด ์ฐ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํฉ๋๋ค:
def fives : String ร Int := ("five", 5)
๋ ํ๊ธฐ๋ฒ ๋ชจ๋ ์ค๋ฅธ์ชฝ ๊ฒฐํฉ์
๋๋ค. ์ด๋ ๋ค์ ์ ์๋ค์ด ๋์ผํ๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค:
def sevens : String ร Int ร Nat := ("VII", 7, 4 + 3)def sevens : String ร (Int ร Nat) := ("VII", (7, 4 + 3))
์ฆ, ์ธ ๊ฐ ์ด์์ ํ์
์ผ๋ก ์ด๋ฃจ์ด์ง ๋ชจ๋ ํ๋ก๋ํธ์ ๊ทธ์ ํด๋นํ๋ ์์ฑ์๋ค์ ์ค์ ๋ก๋ ๋ด๋ถ์ ์ผ๋ก ์ค์ฒฉ๋ ํ๋ก๋ํธ์ ์ค์ฒฉ๋ ์์
๋๋ค.
1.6.3.3. Sum
Sum ๋ฐ์ดํฐ ํ์
์ ๋ ๊ฐ์ง ๋ค๋ฅธ ํ์
์ ๊ฐ ์ฌ์ด์์ ์ ํ์ ํ์ฉํ๋ ์ผ๋ฐ์ ์ธ ๋ฐฉ๋ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, Sum String Int๋ String์ด๊ฑฐ๋ Int์
๋๋ค. Prod์ ๋ง์ฐฌ๊ฐ์ง๋ก, Sum์ ๋งค์ฐ ์ผ๋ฐ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ๋, ํฉ๋ฆฌ์ ์ธ ๋๋ฉ์ธ ํน์ ํ์
์ด ์๋ ๋งค์ฐ ์์ ์ฝ๋ ์น์
์ ๋ํด, ๋๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ์ฉํ ํจ์๊ฐ ํฌํจ๋์ด ์์ ๋ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ๋๋ถ๋ถ์ ์ํฉ์์๋ ์ฌ์ฉ์ ์ ์ ๊ท๋ฉ์ ํ์
์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ๊ฐ๋
์ฑ์ด ์ข๊ณ ์ ์ง๋ณด์ํ๊ธฐ ์ฝ์ต๋๋ค.
Sum ฮฑ ฮฒ ํ์
์ ๊ฐ์ ฮฑ ํ์
์ ๊ฐ์ ์ ์ฉ๋ ์์ฑ์ inl์ด๊ฑฐ๋ ฮฒ ํ์
์ ๊ฐ์ ์ ์ฉ๋ ์์ฑ์ inr์
๋๋ค:
inductive Sum (ฮฑ : Type) (ฮฒ : Type) : Type where | inl : ฮฑ โ Sum ฮฑ ฮฒ | inr : ฮฒ โ Sum ฮฑ ฮฒ
์ด ์ด๋ฆ๋ค์ ๊ฐ๊ฐ "์ผ์ชฝ ์ฌ์(left injection)"๊ณผ "์ค๋ฅธ์ชฝ ์ฌ์(right injection)"์ ์ฝ์ด์
๋๋ค. Prod์ ๋ฐ์นด๋ฅดํธ ๊ณฑ ํ๊ธฐ๋ฒ์ด ์ฌ์ฉ๋๋ ๊ฒ์ฒ๋ผ, Sum์๋ "๋๊ทธ๋ผ๋ฏธ ์์ ๋ํ๊ธฐ" ํ๊ธฐ๋ฒ์ด ์ฌ์ฉ๋๋ฏ๋ก, ฮฑ โ ฮฒ๋ Sum ฮฑ ฮฒ๋ฅผ ์ฐ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์
๋๋ค. Sum.inl๊ณผ Sum.inr์ ๋ํ ํน๋ณํ ๊ตฌ๋ฌธ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์ ์๋๋ฌผ ์ด๋ฆ์ด ๊ฐ ์ด๋ฆ์ด๊ฑฐ๋ ๊ณ ์์ด ์ด๋ฆ์ผ ์ ์๋ค๋ฉด, ๊ทธ๋ค์ ์ํ ํ์
์ ๋ฌธ์์ด์ ํฉ์ผ๋ก ๋์
๋ ์ ์์ต๋๋ค:
def PetName : Type := String โ String
์ค์ ํ๋ก๊ทธ๋จ์์๋, ์ ์ตํ ์์ฑ์ ์ด๋ฆ์ ๊ฐ์ง ์ฌ์ฉ์ ์ ์ ๊ท๋ฉ์ ๋ฐ์ดํฐ ํ์
์ ์ด ๋ชฉ์ ์ผ๋ก ์ ์ํ๋ ๊ฒ์ด ๋ณดํต ๋ ์ข์ต๋๋ค. ์ฌ๊ธฐ์๋, Sum.inl์ ๊ฐ ์ด๋ฆ์, Sum.inr์ ๊ณ ์์ด ์ด๋ฆ์ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ์์ฑ์๋ค์ ์ฌ์ฉํ์ฌ ๋๋ฌผ ์ด๋ฆ ๋ชฉ๋ก์ ์์ฑํ ์ ์์ต๋๋ค:
def animals : List PetName := [Sum.inl "Spot", Sum.inr "Tiger", Sum.inl "Fifi", Sum.inl "Rex", Sum.inr "Floof"]
ํจํด ๋งค์นญ์ ์ฌ์ฉํ์ฌ ๋ ์์ฑ์๋ฅผ ๊ตฌ๋ณํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋๋ฌผ ์ด๋ฆ ๋ชฉ๋ก์์ ๊ฐ์ ์(์ฆ, Sum.inl ์์ฑ์์ ์)๋ฅผ ์ธ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
def howManyDogs (pets : List PetName) : Nat := match pets with | [] => 0 | Sum.inl _ :: morePets => howManyDogs morePets + 1 | Sum.inr _ :: morePets => howManyDogs morePets
ํจ์ ํธ์ถ์ ์ค์ ์ฐ์ฐ์๋ณด๋ค ๋จผ์ ํ๊ฐ๋๋ฏ๋ก, howManyDogs morePets + 1์ (howManyDogs morePets) + 1๊ณผ ๊ฐ์ต๋๋ค. ์์๋๋ก, #eval howManyDogs animals๋ 3์ ์ฐ์ถํฉ๋๋ค.
1.6.3.4. Unit
Unit์ unit์ด๋ผ๋ ๋จ ํ๋์ ์ธ์ ์๋ ์์ฑ์๋ฅผ ๊ฐ์ง ํ์
์
๋๋ค. ์ฆ, ๊ทธ๊ฒ์ ๋จ ํ๋์ ๊ฐ๋ง์ ์ค๋ช
ํ๋ฉฐ, ์ด ๊ฐ์ ์๋ฌด ์ธ์์๋ ์ ์ฉ๋์ง ์์ ํด๋น ์์ฑ์๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. Unit์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋ฉ๋๋ค:
inductive Unit : Type where | unit : Unit
๊ทธ ์์ฒด๋ก Unit์ ํน๋ณํ ์ ์ฉํ์ง ์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋คํ์ฑ ์ฝ๋์์๋ ๋๋ฝ๋ ๋ฐ์ดํฐ๋ฅผ ์ํ ์๋ฆฌ ํ์์๋ก ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์ ๊ท๋ฉ์ ๋ฐ์ดํฐ ํ์
์ ์ฐ์ ํํ์์ ๋ํ๋
๋๋ค:
inductive ArithExpr (ann : Type) : Type where | int : ann โ Int โ ArithExpr ann | plus : ann โ ArithExpr ann โ ArithExpr ann โ ArithExpr ann | minus : ann โ ArithExpr ann โ ArithExpr ann โ ArithExpr ann | times : ann โ ArithExpr ann โ ArithExpr ann โ ArithExpr ann
ํ์
์ธ์ ann์ ์ฃผ์์ ์๋ฏธํ๋ฉฐ, ๊ฐ ์์ฑ์๋ ์ฃผ์์ด ๋ฌ๋ ค ์์ต๋๋ค. ํ์์์ ์ค๋ ํํ์์ ์์ค ์์น๋ก ์ฃผ์์ด ๋ฌ๋ฆด ์ ์์ผ๋ฏ๋ก, ๋ฐํ ํ์
์ด ArithExpr SourcePos์ด๋ฉด ํ์๊ฐ ๊ฐ ํ์ ํํ์์ SourcePos๋ฅผ ๋ฃ์์์ ๋ณด์ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ ํ์์์ ์ค์ง ์์ ํํ์์ ์์ค ์์น๊ฐ ์์ผ๋ฏ๋ก, ๊ทธ ํ์
์ ArithExpr Unit์ด ๋ ์ ์์ต๋๋ค.
๋ํ, ๋ชจ๋ Lean ํจ์๋ ์ธ์๋ฅผ ๊ฐ์ง๋ฏ๋ก, ๋ค๋ฅธ ์ธ์ด์ ์ธ์ ์๋ ํจ์๋ Unit ์ธ์๋ฅผ ๋ฐ๋ ํจ์๋ก ํํ๋ ์ ์์ต๋๋ค. ๋ฐํ ์์น์์ Unit ํ์
์ C์์ ํ์๋ ์ธ์ด์ void์ ์ ์ฌํฉ๋๋ค. C ๊ณ์ด์์ void๋ฅผ ๋ฐํํ๋ ํจ์๋ ํธ์ถ์์๊ฒ ์ ์ด๋ฅผ ๋ฐํํ์ง๋ง, ํฅ๋ฏธ๋ก์ด ๊ฐ์ ๋ฐํํ์ง๋ ์์ต๋๋ค. ์๋์ ์ผ๋ก ํฅ๋ฏธ๋กญ์ง ์์ ๊ฐ์ด ๋จ์ผ๋ก์จ, Unit์ ํ์
์์คํ
์ ํน์ ๋ชฉ์ ์ void ๊ธฐ๋ฅ์ด ํ์ ์์ด ์ด๋ฅผ ํํํ ์ ์๊ฒ ํฉ๋๋ค. Unit์ ์์ฑ์๋ ๋ค์๊ณผ ๊ฐ์ด ๋น ๊ดํธ๋ก ์ธ ์ ์์ต๋๋ค: () : Unit.
1.6.3.5. Empty
Empty ๋ฐ์ดํฐ ํ์
์ ์์ฑ์๊ฐ ์ ํ ์์ต๋๋ค. ๋ฐ๋ผ์, ์ด๋ค ์ผ๋ จ์ ํธ์ถ๋ Empty ํ์
์ ๊ฐ์ผ๋ก ๋๋ ์ ์๊ธฐ ๋๋ฌธ์ ๋๋ฌํ ์ ์๋ ์ฝ๋๋ฅผ ๋ํ๋
๋๋ค.
Empty๋ Unit๋งํผ ์์ฃผ ์ฌ์ฉ๋์ง๋ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ผ๋ถ ํน์ํ ๋งฅ๋ฝ์์ ์ ์ฉํฉ๋๋ค. ๋ง์ ๋คํ์ฑ ๋ฐ์ดํฐ ํ์
์ ๋ชจ๋ ์์ฑ์์์ ๋ชจ๋ ํ์
์ธ์๋ฅผ ์ฌ์ฉํ์ง๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, Sum.inl๊ณผ Sum.inr๋ ๊ฐ๊ฐ Sum์ ํ์
์ธ์ ์ค ํ๋๋ง ์ฌ์ฉํฉ๋๋ค. Sum์ ํ์
์ธ์ ์ค ํ๋๋ก Empty๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋ก๊ทธ๋จ์ ํน์ ์ง์ ์์ ์์ฑ์ ์ค ํ๋๋ฅผ ๋ฐฐ์ ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ถ๊ฐ์ ์ธ ์ ์ฝ์ด ์๋ ๋งฅ๋ฝ์์ ์ผ๋ฐ ์ฝ๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.1.6.3.6. ์ด๋ฆ ์ง๊ธฐ: ํฉ, ๊ณฑ, ๊ทธ๋ฆฌ๊ณ ์ ๋๐
์ผ๋ฐ์ ์ผ๋ก, ์ฌ๋ฌ ์์ฑ์๋ฅผ ์ ๊ณตํ๋ ํ์
์ ํฉ ํ์
(sum type)์ด๋ผ๊ณ ํ๊ณ , ๋จ์ผ ์์ฑ์๊ฐ ์ฌ๋ฌ ์ธ์๋ฅผ ๋ฐ๋ ํ์
์ ๊ณฑ ํ์
(product type)์ด๋ผ๊ณ ํฉ๋๋ค. ์ด ์ฉ์ด๋ค์ ์ผ๋ฐ ์ฐ์ ์์ ์ฌ์ฉ๋๋ ํฉ๊ณผ ๊ณฑ๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค. ์ด ๊ด๊ณ๋ ๊ด๋ จ๋ ํ์
๋ค์ด ์ ํํ ์์ ๊ฐ์ ํฌํจํ ๋ ๊ฐ์ฅ ์ฝ๊ฒ ๋ณผ ์ ์์ต๋๋ค. ๋ง์ฝ ฮฑ์ ฮฒ๊ฐ ๊ฐ๊ฐ n๊ฐ์ k๊ฐ์ ์๋ก ๋ค๋ฅธ ๊ฐ์ ํฌํจํ๋ ํ์
์ด๋ผ๋ฉด, ฮฑ โ ฮฒ๋ n+k๊ฐ์ ์๋ก ๋ค๋ฅธ ๊ฐ์ ํฌํจํ๊ณ ฮฑ ร ฮฒ๋ nรk๊ฐ์ ์๋ก ๋ค๋ฅธ ๊ฐ์ ํฌํจํฉ๋๋ค. ์๋ฅผ ๋ค์ด, Bool์ true์ false ๋ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๊ณ , Unit์ Unit.unit์ด๋ผ๋ ํ๋์ ๊ฐ์ ๊ฐ์ง๋๋ค. ๊ณฑ Bool ร Unit์ (true, Unit.unit)๊ณผ (false, Unit.unit) ๋ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๊ณ , ํฉ Bool โ Unit์ Sum.inl true, Sum.inl false, Sum.inr Unit.unit ์ธ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก, 2ร1=2์ด๊ณ , 2+1=3์
๋๋ค.
1.6.4. ๋ง์ฃผ์น ์ ์๋ ๋ฉ์์ง๋ค
์ ์ ๊ฐ๋ฅํ ๋ชจ๋ ๊ตฌ์กฐ์ฒด๋ ๊ท๋ฉ์ ํ์
์ด Type ํ์
์ ๊ฐ์ง ์ ์๋ ๊ฒ์ ์๋๋๋ค. ํนํ, ์์ฑ์๊ฐ ์์์ ํ์
์ ์ธ์๋ก ๋ฐ๋ ๊ฒฝ์ฐ, ๊ท๋ฉ์ ํ์
์ ๋ค๋ฅธ ํ์
์ ๊ฐ์ ธ์ผ ํฉ๋๋ค. ์ด๋ฌํ ์ค๋ฅ๋ ๋ณดํต "์ ๋๋ฒ์ค ๋ ๋ฒจ"์ ๋ํ ๋ฌด์ธ๊ฐ๋ฅผ ๋ช
์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ด ๊ท๋ฉ์ ํ์
์ ๋ํด:
inductive MyType : Type where | ctor : (ฮฑ : Type) โ ฮฑ โ MyType
Lean์ ๋ค์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค:
Invalid universe level in constructor `MyType.ctor`: Parameter `ฮฑ` has type Typeat universe level 2which is not less than or equal to the inductive type's resulting universe level 1
์ด๊ฒ์ด ์ ๊ทธ๋ฐ์ง, ๊ทธ๋ฆฌ๊ณ ์ ์๋ฅผ ์์ ํ์ฌ ์๋ํ๊ฒ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋์ค ์ฅ์์ ์ค๋ช
ํฉ๋๋ค. ์ง๊ธ์ ํ์
์ ์์ฑ์์ ๋ํ ์ธ์๊ฐ ์๋ ๊ท๋ฉ์ ํ์
์ ์ฒด์ ๋ํ ์ธ์๋ก ๋ง๋ค์ด ๋ณด์ธ์.
๋ง์ฐฌ๊ฐ์ง๋ก, ์์ฑ์์ ์ธ์๊ฐ ์ ์๋๊ณ ์๋ ๋ฐ์ดํฐ ํ์
์ ์ธ์๋ก ๋ฐ๋ ํจ์์ธ ๊ฒฝ์ฐ, ์ ์๋ ๊ฑฐ๋ถ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด:
inductive MyType : Type where | ctor : (MyType โ Int) โ MyType
๋ค์ ๋ฉ์์ง๋ฅผ ์ฐ์ถํฉ๋๋ค:
(kernel) arg #1 of 'MyType.ctor' has a non positive occurrence of the datatypes being declared
๊ธฐ์ ์ ์ธ ์ด์ ๋ก, ์ด๋ฌํ ๋ฐ์ดํฐ ํ์
์ ํ์ฉํ๋ฉด Lean์ ๋ด๋ถ ๋
ผ๋ฆฌ๋ฅผ ์ฝํ์์ผ ์ ๋ฆฌ ์ฆ๋ช
๊ธฐ๋ก์ ์ฌ์ฉํ๊ธฐ์ ๋ถ์ ํฉํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
๋ ๊ฐ์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ๋ ์ฌ๊ท ํจ์๋ ์์ ๋ํด ๋งค์นํด์๋ ์ ๋๋ฉฐ, ๊ฐ ๋งค๊ฐ๋ณ์๋ฅผ ๋
๋ฆฝ์ ์ผ๋ก ๋งค์นํด์ผ ํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด, Lean์์ ์ฌ๊ท ํธ์ถ์ด ๋ ์์ ๊ฐ์ ๋ํด ์ด๋ฃจ์ด์ง๋์ง ํ์ธํ๋ ๋ฉ์ปค๋์ฆ์ด ์
๋ ฅ ๊ฐ๊ณผ ์ฌ๊ท ํธ์ถ์ ์ธ์ ์ฌ์ด์ ์ฐ๊ฒฐ์ ๋ณผ ์ ์๊ฒ ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ ๋ฆฌ์คํธ์ ๊ธธ์ด๊ฐ ๊ฐ์์ง ํ๋ณํ๋ ์ด ํจ์๋ ๊ฑฐ๋ถ๋ฉ๋๋ค:
def sameLength (xs : List ฮฑ) (ys : List ฮฒ) : Bool := match (xs, ys) with | ([], []) => true | (x :: xs', y :: ys') => sameLength xs' ys' | _ => false
์ค๋ฅ ๋ฉ์์ง๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
fail to show termination for sameLengthwith errorsfailed to infer structural recursion:Not considering parameter ฮฑ of sameLength: it is unchanged in the recursive callsNot considering parameter ฮฒ of sameLength: it is unchanged in the recursive callsCannot use parameter xs: failed to eliminate recursive application sameLength xs' ys'Cannot use parameter ys: failed to eliminate recursive application sameLength xs' ys'Could not find a decreasing measure.The basic measures relate at each recursive call as follows:(<, โค, =: relation proved, ? all proofs failed, _: no proof attempted) xs ys1) 1816:28-46 ? ?Please use `termination_by` to specify a decreasing measure.
์ด ๋ฌธ์ ๋ ์ค์ฒฉ๋ ํจํด ๋งค์นญ์ ํตํด ํด๊ฒฐํ ์ ์์ต๋๋ค:
def sameLength (xs : List ฮฑ) (ys : List ฮฒ) : Bool := match xs with | [] => match ys with | [] => true | _ => false | x :: xs' => match ys with | y :: ys' => sameLength xs' ys' | _ => false
๋ค์ ์น์
์์ ์ค๋ช
ํ๋ ๋์ ๋งค์นญ์ ์ข
์ข
๋ ์ฐ์ํ๊ฒ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์
๋๋ค.
๊ท๋ฉ์ ํ์
์ ๋ํ ์ธ์๋ฅผ ์์ด๋ฒ๋ฆฌ๋ ๊ฒ๋ ํผ๋์ค๋ฌ์ด ๋ฉ์์ง๋ฅผ ๋ณ์ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ctor์ ํ์
์์ MyType์ ์ธ์ ฮฑ๊ฐ ์ ๋ฌ๋์ง ์์์ ๋:
inductive MyType (ฮฑ : Type) : Type where | ctor : ฮฑ โ MyType
Lean์ ๋ค์ ์ค๋ฅ๋ก ์๋ตํฉ๋๋ค:
type expected, got (MyType : Type โ Type)
์ค๋ฅ ๋ฉ์์ง๋ MyType์ ํ์
์ธ Type โ Type์ด ๊ทธ ์์ฒด๋ก๋ ํ์
์ ์ค๋ช
ํ์ง ์๋๋ค๊ณ ๋งํ๊ณ ์์ต๋๋ค. MyType์ ์ค์ ์ ์งํ ํ์
์ด ๋๊ธฐ ์ํด ์ธ์๊ฐ ํ์ํฉ๋๋ค.
์ ์์ ํ์
์๊ทธ๋์ฒ์ ๊ฐ์ ๋ค๋ฅธ ๋งฅ๋ฝ์์ ํ์
์ธ์๊ฐ ์๋ต๋ ๋๋ ๋์ผํ ๋ฉ์์ง๊ฐ ๋ํ๋ ์ ์์ต๋๋ค:
inductive MyType (ฮฑ : Type) : Type where | ctor : ฮฑ โ MyType ฮฑdef ofFive : MyType := ctor 5type expected, got (MyType : Type โ Type)
๋คํ์ฑ ํ์
์ ์ฌ์ฉํ๋ ํํ์์ ํ๊ฐํ๋ฉด Lean์ด ๊ฐ์ ํ์ํ ์ ์๋ ์ํฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค. #eval ๋ช
๋ น์ด๋ ์ ๊ณต๋ ํํ์์ ํ๊ฐํ๊ณ , ํํ์์ ํ์
์ ์ฌ์ฉํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํฉ๋๋ค. ํจ์์ ๊ฐ์ ์ผ๋ถ ํ์
์ ๊ฒฝ์ฐ ์ด ๊ณผ์ ์ด ์คํจํ์ง๋ง, Lean์ ๋๋ถ๋ถ์ ๋ค๋ฅธ ํ์
์ ๋ํด ํ์ ์ฝ๋๋ฅผ ์๋์ผ๋ก ์์ฑํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, WoodSplittingTool์ ๋ํด Lean์ ํน์ ํ์ ์ฝ๋๋ฅผ ์ ๊ณตํ ํ์๊ฐ ์์ต๋๋ค:
inductive WoodSplittingTool where | axe | maul | froe#eval WoodSplittingTool.axeWoodSplittingTool.axe
๊ทธ๋ฌ๋ Lean์ด ์ฌ๊ธฐ์ ์ฌ์ฉํ๋ ์๋ํ์๋ ํ๊ณ๊ฐ ์์ต๋๋ค. allTools๋ ์ธ ๊ฐ์ง ๋๊ตฌ ๋ชจ๋๋ฅผ ๋ด์ ๋ฆฌ์คํธ์
๋๋ค:
def allTools : List WoodSplittingTool := [ WoodSplittingTool.axe, WoodSplittingTool.maul, WoodSplittingTool.froe]
์ด๋ฅผ ํ๊ฐํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค:
#eval allToolscould not synthesize a `ToExpr`, `Repr`, or `ToString` instance for type List WoodSplittingTool
์ด๋ Lean์ด ๋ฆฌ์คํธ๋ฅผ ํ์ํ๊ธฐ ์ํด ๋ด์ฅ ํ
์ด๋ธ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ์๋ํ์ง๋ง, ์ด ์ฝ๋๋ WoodSplittingTool์ ๋ํ ํ์ ์ฝ๋๊ฐ ์ด๋ฏธ ์กด์ฌํด์ผ ํ๋ค๊ณ ์๊ตฌํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด ์ค๋ฅ๋ ๋ฐ์ดํฐ ํ์
์ ์ ์ํ ๋ #eval์ ์ผ๋ถ๋ก ๋ง์ง๋ง ์๊ฐ์ ์์ฑํ๋ ๋์ , Lean์๊ฒ ์ด ํ์ ์ฝ๋๋ฅผ ์์ฑํ๋๋ก ์ง์ํจ์ผ๋ก์จ ํด๊ฒฐํ ์ ์์ต๋๋ค. ์ ์์ deriving Repr์ ์ถ๊ฐํ๋ฉด ๋ฉ๋๋ค:
inductive Firewood where | birch | pine | beechderiving Repr
Firewood ๋ฆฌ์คํธ๋ฅผ ํ๊ฐํ๋ ๊ฒ์ ์ฑ๊ณตํฉ๋๋ค:
def allFirewood : List Firewood := [ Firewood.birch, Firewood.pine, Firewood.beech]#eval allFirewood[Firewood.birch, Firewood.pine, Firewood.beech]
1.6.5. ์ฐ์ต ๋ฌธ์
๋ฆฌ์คํธ์ ๋ง์ง๋ง ํญ๋ชฉ์ ์ฐพ๋ ํจ์๋ฅผ ์์ฑํ์ธ์. ์ด ํจ์๋ Option์ ๋ฐํํด์ผ ํฉ๋๋ค.
์ฃผ์ด์ง ์ ์ด๋ฅผ ๋ง์กฑํ๋ ๋ฆฌ์คํธ์ ์ฒซ ๋ฒ์งธ ํญ๋ชฉ์ ์ฐพ๋ ํจ์๋ฅผ ์์ฑํ์ธ์. ์ ์๋ ๋ค์์ฒ๋ผ ์์ํด์ผํฉ๋๋ค:def List.findFirst? {ฮฑ : Type} (xs : List ฮฑ) (predicate : ฮฑ โ Bool) : Option ฮฑ :=
์์ ๋ ํ๋๋ฅผ ์๋ก ๋ฐ๊พธ๋ Prod.switch ํจ์๋ฅผ ์์ฑํ์ธ์. ์ ์๋ ๋ค์์ฒ๋ผ ์์ํด์ผํฉ๋๋ค:def Prod.switch {ฮฑ ฮฒ : Type} (pair : ฮฑ ร ฮฒ) : ฮฒ ร ฮฑ :=
PetName ์์ ๋ฅผ ์ฌ์ฉ์ ์ ์ ๋ฐ์ดํฐ ํ์
์ ์ฌ์ฉํ๋๋ก ๋ค์ ์์ฑํ๊ณ Sum์ ์ฌ์ฉํ ๋ฒ์ ๊ณผ ๋น๊ตํด ๋ณด์ธ์.
๋ ๋ฆฌ์คํธ๋ฅผ ์์ ๋ฆฌ์คํธ๋ก ๊ฒฐํฉํ๋ zip ํจ์๋ฅผ ์์ฑํ์ธ์. ๊ฒฐ๊ณผ ๋ฆฌ์คํธ๋ ๊ฐ์ฅ ์งง์ ์
๋ ฅ ๋ฆฌ์คํธ์ ๊ธธ์ด์ ๊ฐ์์ผ ํฉ๋๋ค. ์ ์๋ ๋ค์์ฒ๋ผ ์์ํด์ผํฉ๋๋ค:def zip {ฮฑ ฮฒ : Type} (xs : List ฮฑ) (ys : List ฮฒ) : List (ฮฑ ร ฮฒ) :=
๋ฆฌ์คํธ์ ์ฒซ n๊ฐ ํญ๋ชฉ์ ๋ฐํํ๋ ๋คํ์ฑ ํจ์ take๋ฅผ ์์ฑํ์ธ์. ์ฌ๊ธฐ์ n์ Nat์
๋๋ค. ๋ฆฌ์คํธ์ n๊ฐ ๋ฏธ๋ง์ ํญ๋ชฉ์ด ํฌํจ๋ ๊ฒฝ์ฐ, ๊ฒฐ๊ณผ ๋ฆฌ์คํธ๋ ์ ์ฒด ์
๋ ฅ ๋ฆฌ์คํธ์ฌ์ผ ํฉ๋๋ค. #eval take 3 ["bolete", "oyster"]๋ ["bolete", "oyster"]๋ฅผ ์ฐ์ถํด์ผ ํ๊ณ , #eval take 1 ["bolete", "oyster"]๋ ["bolete"]๋ฅผ ์ฐ์ถํด์ผ ํฉ๋๋ค.
ํ์
๊ณผ ์ฐ์ ์ฌ์ด์ ์ ์ถ๋ฅผ ์ฌ์ฉํ์ฌ, ๊ณฑ์ ํฉ์ ๋ํด ๋ถ๋ฐฐํ๋ ํจ์๋ฅผ ์์ฑํ์ธ์. ์ฆ, ์ด ํจ์๋ ฮฑ ร (ฮฒ โ ฮณ) โ (ฮฑ ร ฮฒ) โ (ฮฑ ร ฮณ) ํ์
์ ๊ฐ์ ธ์ผ ํฉ๋๋ค.
ํ์
๊ณผ ์ฐ์ ์ฌ์ด์ ์ ์ถ๋ฅผ ์ฌ์ฉํ์ฌ, 2๋ฅผ ๊ณฑํ๋ ๊ฒ์ ํฉ์ผ๋ก ๋ฐ๊พธ๋ ํจ์๋ฅผ ์์ฑํ์ธ์. ์ฆ, ์ด ํจ์๋ Bool ร ฮฑ โ ฮฑ โ ฮฑ ํ์
์ ๊ฐ์ ธ์ผ ํฉ๋๋ค.
1.7. ์ถ๊ฐ์ ์ธ ํธ์ ๊ธฐ๋ฅ
Lean์๋ ํ๋ก๊ทธ๋จ์ ํจ์ฌ ๋ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค์ด์ฃผ๋ ์ฌ๋ฌ ํธ์ ๊ธฐ๋ฅ์ด ํฌํจ๋์ด ์์ต๋๋ค.
1.7.1. ์๋ ์์์ ๋งค๊ฐ๋ณ์
Lean์์ ๋คํ์ฑ ํจ์๋ฅผ ์์ฑํ ๋, ์ผ๋ฐ์ ์ผ๋ก ๋ชจ๋ ์์์ ๋งค๊ฐ๋ณ์๋ฅผ ๋์ดํ ํ์๋ ์์ต๋๋ค. ๋์ , ๊ทธ๋ฅ ์ธ๊ธํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. Lean์ด ๊ทธ ํ์
์ ๊ฒฐ์ ํ ์ ์๋ค๋ฉด, ํด๋น ๋งค๊ฐ๋ณ์๋ค์ ์๋์ผ๋ก ์์์ ๋งค๊ฐ๋ณ์๋ก ์ฝ์
๋ฉ๋๋ค. ๋ค์ ๋งํด, ์ด์ ์ ์ ์ํ๋ length๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def length {ฮฑ : Type} (xs : List ฮฑ) : Nat := match xs with | [] => 0 | y :: ys => Nat.succ (length ys)
์ด ์ ์๋ {ฮฑ : Type} ์์ด๋ ์์ฑํ ์ ์์ต๋๋ค.
def length (xs : List ฮฑ) : Nat := match xs with | [] => 0 | y :: ys => Nat.succ (length ys)
์ด ๊ธฐ๋ฅ์ ๋ง์ ์์์ ๋งค๊ฐ๋ณ์๋ฅผ ์ฌ์ฉํ๋ ๊ณ ๋๋ก ๋คํ์ ์ธ ์ ์๋ฅผ ํฌ๊ฒ ๋จ์ํํ ์ ์์ต๋๋ค.
1.7.2. ํจํด ๋งค์นญ ์ ์
def๋ก ํจ์๋ฅผ ์ ์ํ ๋, ์ธ์์ ์ด๋ฆ์ ์ง์ ํ ํ ๋ฐ๋ก ํจํด ๋งค์นญ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋งค์ฐ ํํฉ๋๋ค. ์๋ฅผ ๋ค์ด, length์์ ์ธ์ xs๋ match์์๋ง ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฐ ์ํฉ์์๋ ์ธ์์ ์ด๋ฆ์ ์ ํ ์ง์ ํ์ง ์๊ณ match ํํ์์ ์ผ์ด์ค๋ค์ ์ง์ ์์ฑํ ์ ์์ต๋๋ค.
์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ์ธ์์ ํ์
์ ์ฝ๋ก ์ค๋ฅธ์ชฝ์ผ๋ก ์ฎ๊ฒจ์ ๋ฐํ ํ์
์ด ํจ์ ํ์
์ด ๋๋๋ก ํ๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, length์ ํ์
์ List ฮฑ โ Nat์
๋๋ค. ๊ทธ๋ฐ ๋ค์, :=๋ฅผ ๊ฐ ํจํด ๋งค์นญ ์ผ์ด์ค๋ก ๋์ฒดํฉ๋๋ค.
def length : List ฮฑ โ Nat | [] => 0 | y :: ys => Nat.succ (length ys)
์ด ๊ตฌ๋ฌธ์ ํ๋ ์ด์์ ์ธ์๋ฅผ ๋ฐ๋ ํจ์๋ฅผ ์ ์ํ๋ ๋ฐ์๋ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ, ํจํด๋ค์ ์ผํ๋ก ๊ตฌ๋ถ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, drop์ ์ซ์ nn๊ณผ ๋ฆฌ์คํธ๋ฅผ ๋ฐ์ ์ฒ์ nn๊ฐ์ ํญ๋ชฉ์ ์ ๊ฑฐํ ํ์ ๋ฆฌ์คํธ๋ฅผ ๋ฐํํฉ๋๋ค.
def drop : Nat โ List ฮฑ โ List ฮฑ | Nat.zero, xs => xs | _, [] => [] | Nat.succ n, x :: xs => drop n xs
์ด๋ฆ์ด ์ง์ ๋ ์ธ์์ ํจํด์ ๊ฐ์ ์ ์ ์์์ ํจ๊ป ์ฌ์ฉํ ์๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๊ธฐ๋ณธ๊ฐ๊ณผ ์ต์
๋ ๊ฐ์ ๋ฐ์ ์ต์
๋ ๊ฐ์ด none์ผ ๋ ๊ธฐ๋ณธ๊ฐ์ ๋ฐํํ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
def fromOption (default : ฮฑ) : Option ฮฑ โ ฮฑ | none => default | some x => x
์ด ํจ์๋ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ Option.getD๋ผ๊ณ ๋ถ๋ฆฌ๋ฉฐ, ์ ํ๊ธฐ๋ฒ์ผ๋ก ํธ์ถํ ์ ์์ต๋๋ค.
#eval (some "salmonberry").getD """salmonberry"#eval none.getD """"
1.7.3. ์ง์ญ ์ ์
๊ณ์ฐ ๊ณผ์ ์์ ์ค๊ฐ ๋จ๊ณ๋ฅผ ๋ช
๋ช
ํ๋ ๊ฒ์ ์ข
์ข
์ ์ฉํฉ๋๋ค. ๋ง์ ๊ฒฝ์ฐ, ์ค๊ฐ๊ฐ๋ค์ ๊ทธ ์์ฒด๋ก ์ ์ฉํ ๊ฐ๋
์ ๋ํ๋ด๋ฉฐ, ์ด๋ฅผ ๋ช
์์ ์ผ๋ก ๋ช
๋ช
ํ๋ฉด ํ๋ก๊ทธ๋จ์ ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค. ๋ค๋ฅธ ๊ฒฝ์ฐ์๋ ์ค๊ฐ๊ฐ์ด ๋ ๋ฒ ์ด์ ์ฌ์ฉ๋ฉ๋๋ค. ๋๋ถ๋ถ์ ๋ค๋ฅธ ์ธ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก, Lean์์ ๋์ผํ ์ฝ๋๋ฅผ ๋ ๋ฒ ์์ฑํ๋ฉด ๋ ๋ฒ ๊ณ์ฐ๋์ง๋ง, ๊ฒฐ๊ณผ๋ฅผ ๋ณ์์ ์ ์ฅํ๋ฉด ๊ณ์ฐ ๊ฒฐ๊ณผ๊ฐ ์ ์ฅ๋์ด ์ฌ์ฌ์ฉ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, unzip์ ์์ ๋ฆฌ์คํธ๋ฅผ ๋ฆฌ์คํธ์ ์์ผ๋ก ๋ณํํ๋ ํจ์์
๋๋ค. ์์ ๋ฆฌ์คํธ๊ฐ ๋น์ด ์์ผ๋ฉด, unzip์ ๊ฒฐ๊ณผ๋ ๋น ๋ฆฌ์คํธ์ ์์
๋๋ค. ์์ ๋ฆฌ์คํธ๊ฐ ๋จธ๋ฆฌ์ ์์ ๊ฐ์ง๊ณ ์์ผ๋ฉด, ๊ทธ ์์ ๋ ํ๋๋ ๋ฆฌ์คํธ์ ๋๋จธ์ง ๋ถ๋ถ์ unzipํ ๊ฒฐ๊ณผ์ ์ถ๊ฐ๋ฉ๋๋ค. ์ด unzip์ ์ ์๋ ๊ทธ ์ค๋ช
์ ์ ํํ ๋ฐ๋ฆ
๋๋ค.
def unzip : List (ฮฑ ร ฮฒ) โ List ฮฑ ร List ฮฒ | [] => ([], []) | (x, y) :: xys => (x :: (unzip xys).fst, y :: (unzip xys).snd)
๋ถํํ๋, ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ด ์ฝ๋๋ ํ์ ์ด์์ผ๋ก ๋๋ฆฝ๋๋ค. ์์ ๋ฆฌ์คํธ์ ์๋ ๊ฐ ํญ๋ชฉ์ ๋ ๋ฒ์ ์ฌ๊ท ํธ์ถ๋ก ์ด์ด์ ธ, ์ด ํจ์๊ฐ ์ง์ ์๊ฐ์ ์์ํ๊ฒ ๋ง๋ญ๋๋ค. ํ์ง๋ง ๋ ์ฌ๊ท ํธ์ถ์ ๋ชจ๋ ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ผ ๊ฒ์ด๋ฏ๋ก, ์ฌ๊ท ํธ์ถ์ ๋ ๋ฒ ํ ์ด์ ๊ฐ ์์ต๋๋ค.
Lean์์๋ let์ ์ฌ์ฉํ์ฌ ์ฌ๊ท ํธ์ถ์ ๊ฒฐ๊ณผ๋ฅผ ๋ช
๋ช
ํ๊ณ ์ ์ฅํ ์ ์์ต๋๋ค. let์ ์ฌ์ฉํ ์ง์ญ ์ ์๋ def๋ฅผ ์ฌ์ฉํ ์ต์์ ์ ์์ ์ ์ฌํฉ๋๋ค. ์ง์ญ์ ์ผ๋ก ์ ์๋ ์ด๋ฆ, ์ํ๋ค๋ฉด ์ธ์, ํ์
์๊ทธ๋์ฒ, ๊ทธ๋ฆฌ๊ณ := ๋ค์ ์ค๋ ๋ณธ๋ฌธ์ ๊ฐ์ง๋๋ค. ์ง์ญ ์ ์ ํ, ํด๋น ์ง์ญ ์ ์๊ฐ ์ฌ์ฉ ๊ฐ๋ฅํ ํํ์(let ํํ์์ ๋ณธ๋ฌธ)์ let ํค์๋์ ์ด๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ ์ด์์ ์์ํ๋ ์ ์ค์ ์์ด์ผ ํฉ๋๋ค. unzip์์ let์ ์ฌ์ฉํ ์ง์ญ ์ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def unzip : List (ฮฑ ร ฮฒ) โ List ฮฑ ร List ฮฒ | [] => ([], []) | (x, y) :: xys => let unzipped : List ฮฑ ร List ฮฒ := unzip xys (x :: unzipped.fst, y :: unzipped.snd)
let์ ํ ์ค์์ ์ฌ์ฉํ๋ ค๋ฉด, ์ง์ญ ์ ์์ ๋ณธ๋ฌธ์ ์ธ๋ฏธ์ฝ๋ก ์ผ๋ก ๊ตฌ๋ถํฉ๋๋ค.
let์ ์ฌ์ฉํ ์ง์ญ ์ ์๋ ๋ฐ์ดํฐ ํ์
์ ๋ชจ๋ ์ผ์ด์ค๋ฅผ ํ๋์ ํจํด์ผ๋ก ๋งค์นญํ ์ ์์ ๋ ํจํด ๋งค์นญ์ ์ฌ์ฉํ ์๋ ์์ต๋๋ค. unzip์ ๊ฒฝ์ฐ, ์ฌ๊ท ํธ์ถ์ ๊ฒฐ๊ณผ๋ ์์
๋๋ค. ์์ ๋จ ํ๋์ ์์ฑ์๋ง ๊ฐ์ง๋ฏ๋ก, unzipped๋ผ๋ ์ด๋ฆ์ ์ ํจํด์ผ๋ก ๋์ฒดํ ์ ์์ต๋๋ค.
def unzip : List (ฮฑ ร ฮฒ) โ List ฮฑ ร List ฮฒ | [] => ([], []) | (x, y) :: xys => let (xs, ys) : List ฮฑ ร List ฮฒ := unzip xys (x :: xs, y :: ys)
let๊ณผ ํจ๊ป ํจํด์ ์ ์ ํ ์ฌ์ฉํ๋ฉด, ์ ๊ทผ์ ํธ์ถ์ ์ง์ ์์ฑํ๋ ๊ฒ๋ณด๋ค ์ฝ๋๋ฅผ ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
let๊ณผ def์ ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ์ ์ฌ๊ท์ ์ธ let ์ ์๋ let rec์ ์์ฑํ์ฌ ๋ช
์์ ์ผ๋ก ํ์ํด์ผ ํ๋ค๋ ๊ฒ์
๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฆฌ์คํธ๋ฅผ ๋ค์ง๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ด ์ฌ๊ท์ ์ธ ํฌํผ ํจ์๋ฅผ ํฌํจํฉ๋๋ค.
def reverse (xs : List ฮฑ) : List ฮฑ := let rec helper : List ฮฑ โ List ฮฑ โ List ฮฑ | [], soFar => soFar | y :: ys, soFar => helper ys (y :: soFar) helper xs []
ํฌํผ ํจ์๋ ์
๋ ฅ ๋ฆฌ์คํธ๋ฅผ ๋ฐ๋ผ ๋ด๋ ค๊ฐ๋ฉด์ ํ ๋ฒ์ ํ๋์ ํญ๋ชฉ์ soFar๋ก ์ฎ๊น๋๋ค. ์
๋ ฅ ๋ฆฌ์คํธ์ ๋์ ๋๋ฌํ๋ฉด, soFar๋ ์
๋ ฅ์ ๋ค์งํ ๋ฒ์ ์ ๋ด๊ณ ์์ต๋๋ค.
1.7.4. ํ์
์ถ๋ก
๋ง์ ์ํฉ์์ Lean์ ํํ์์ ํ์
์ ์๋์ผ๋ก ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ, ๋ช
์์ ์ธ ํ์
์ ์ต์์ ์ ์(def ์ฌ์ฉ)์ ์ง์ญ ์ ์(let ์ฌ์ฉ) ๋ชจ๋์์ ์๋ต๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, unzip์ ๋ํ ์ฌ๊ท ํธ์ถ์ ์ด๋
ธํ
์ด์
์ด ํ์ํ์ง ์์ต๋๋ค.
def unzip : List (ฮฑ ร ฮฒ) โ List ฮฑ ร List ฮฒ | [] => ([], []) | (x, y) :: xys => let unzipped := unzip xys (x :: unzipped.fst, y :: unzipped.snd)
๊ฒฝํ์ ์ผ๋ก, ๋ฌธ์์ด์ด๋ ์ซ์์ ๊ฐ์ ๋ฆฌํฐ๋ด ๊ฐ์ ํ์
์ ์๋ตํ๋ ๊ฒ์ ๋ณดํต ์ ์๋ํ์ง๋ง, Lean์ด ๋ฆฌํฐ๋ด ์ซ์์ ๋ํด ์๋ํ ํ์
๋ณด๋ค ๋ ๊ตฌ์ฒด์ ์ธ ํ์
์ ์ ํํ ์ ์์ต๋๋ค. Lean์ ํจ์ ์ ์ฉ์ ๋ํ ํ์
์ ๋ณดํต ๊ฒฐ์ ํ ์ ์๋๋ฐ, ์ด๋ ์ด๋ฏธ ์ธ์ ํ์
๊ณผ ๋ฐํ ํ์
์ ์๊ณ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ํจ์ ์ ์์ ๋ฐํ ํ์
์ ์๋ตํ๋ ๊ฒ์ ์ข
์ข
์๋ํ์ง๋ง, ํจ์ ๋งค๊ฐ๋ณ์๋ ์ผ๋ฐ์ ์ผ๋ก ์ด๋
ธํ
์ด์
์ด ํ์ํฉ๋๋ค. ์์ ์ unzipped์ ๊ฐ์ด ํจ์๊ฐ ์๋ ์ ์๋, ๊ทธ ๋ณธ๋ฌธ์ด ํ์
์ด๋
ธํ
์ด์
์ ํ์๋ก ํ์ง ์๋๋ค๋ฉด ํ์
์ด๋
ธํ
์ด์
์ด ํ์ ์์ผ๋ฉฐ, ์ด ์ ์์ ๋ณธ๋ฌธ์ ํจ์ ์ ์ฉ์
๋๋ค.
๋ช
์์ ์ธ match ํํ์์ ์ฌ์ฉํ ๋ unzip์ ๋ฐํ ํ์
์ ์๋ตํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค.
def unzip (pairs : List (ฮฑ ร ฮฒ)) := match pairs with | [] => ([], []) | (x, y) :: xys => let unzipped := unzip xys (x :: unzipped.fst, y :: unzipped.snd)
์ผ๋ฐ์ ์ผ๋ก, ํ์
์ด๋
ธํ
์ด์
์ ์ ์ ๊ฒ๋ณด๋ค ๋ง์ ํธ์ด ์ข์ต๋๋ค. ์ฒซ์งธ, ๋ช
์์ ์ธ ํ์
์ ์ฝ๋์ ๋ํ ๊ฐ์ ์ ๋
์์๊ฒ ์ ๋ฌํฉ๋๋ค. Lean์ด ์ค์ค๋ก ํ์
์ ๊ฒฐ์ ํ ์ ์๋๋ผ๋, Lean์๊ฒ ๋ฐ๋ณต์ ์ผ๋ก ํ์
์ ๋ณด๋ฅผ ๋ฌป์ง ์๊ณ ์ฝ๋๋ฅผ ์ฝ๋ ๊ฒ์ด ๋ ์ฌ์ธ ์ ์์ต๋๋ค. ๋์งธ, ๋ช
์์ ์ธ ํ์
์ ์ค๋ฅ๋ฅผ ๊ตญ์ํํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ํ๋ก๊ทธ๋จ์ด ํ์
์ ๋ํด ๋ ๋ช
์์ ์ผ์๋ก ์ค๋ฅ ๋ฉ์์ง๊ฐ ๋ ์ ์ตํ ์ ์์ต๋๋ค. ์ด๋ Lean๊ณผ ๊ฐ์ด ๋งค์ฐ ํํ๋ ฅ์ด ํ๋ถํ ํ์
์์คํ
์ ๊ฐ์ง ์ธ์ด์์ ํนํ ์ค์ํฉ๋๋ค. ์
์งธ, ๋ช
์์ ์ธ ํ์
์ ์ ์ด์ ํ๋ก๊ทธ๋จ์ ์์ฑํ๊ธฐ ์ฝ๊ฒ ๋ง๋ญ๋๋ค. ํ์
์ ๋ช
์ธ์ด๋ฉฐ, ์ปดํ์ผ๋ฌ์ ํผ๋๋ฐฑ์ ๋ช
์ธ๋ฅผ ์ถฉ์กฑํ๋ ํ๋ก๊ทธ๋จ์ ์์ฑํ๋ ๋ฐ ์ ์ฉํ ๋๊ตฌ๊ฐ ๋ ์ ์์ต๋๋ค. ๋ง์ง๋ง์ผ๋ก, Lean์ ํ์
์ถ๋ก ์ ์ต์ ๋
ธ๋ ฅ ์์คํ
์
๋๋ค. Lean์ ํ์
์์คํ
์ด ๋งค์ฐ ํํ๋ ฅ์ด ํ๋ถํ๊ธฐ ๋๋ฌธ์, ๋ชจ๋ ํํ์์ ๋ํด "์ต๊ณ ์" ๋๋ ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ํ์
์ ์ฐพ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค. ์ด๋ ํ์
์ ์ป๋๋ผ๋ ์ฃผ์ด์ง ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง๋ ์ฌ๋ฐ๋ฅธ ํ์
์ด๋ผ๋ ๋ณด์ฅ์ด ์๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ์๋ฅผ ๋ค์ด, 14๋ Nat ๋๋ Int๊ฐ ๋ ์ ์์ต๋๋ค.
#check 1414 : Nat#check (14 : Int)14 : Int
ํ์
์ด๋
ธํ
์ด์
์ด ๋๋ฝ๋๋ฉด ํผ๋์ค๋ฌ์ด ์ค๋ฅ ๋ฉ์์ง๊ฐ ๋ํ๋ ์ ์์ต๋๋ค. unzip ์ ์์์ ๋ชจ๋ ํ์
์ ์๋ตํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def unzip pairs := match pairs with | [] => ([], []) | (x, y) :: xys => let unzipped := unzip xys (x :: unzipped.fst, y :: unzipped.snd)
์ด๋ match ํํ์์ ๋ํ ๋ฉ์์ง๋ก ์ด์ด์ง๋๋ค.
Invalid match expression: This pattern contains metavariables: []
์ด๋ match๊ฐ ๊ฒ์ฌ๋๋ ๊ฐ์ ํ์
์ ์์์ผ ํ์ง๋ง, ๊ทธ ํ์
์ด ์ ๊ณต๋์ง ์์๊ธฐ ๋๋ฌธ์
๋๋ค. "๋ฉํ๋ณ์"๋ ํ๋ก๊ทธ๋จ์ ์ ์ ์๋ ๋ถ๋ถ์ผ๋ก, ์ค๋ฅ ๋ฉ์์ง์์๋ ?m.XYZ๋ก ํ์๋๋ฉฐ, ๋คํ์ฑ ์น์
์์ ์ค๋ช
๋ฉ๋๋ค. ์ด ํ๋ก๊ทธ๋จ์์๋ ์ธ์์ ๋ํ ํ์
์ด๋
ธํ
์ด์
์ด ํ์ํฉ๋๋ค.
๋งค์ฐ ๊ฐ๋จํ ํ๋ก๊ทธ๋จ์กฐ์ฐจ๋ ํ์
์ด๋
ธํ
์ด์
์ด ํ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ํญ๋ฑ ํจ์๋ ์ ๋ฌ๋ ์ธ์๋ฅผ ๊ทธ๋๋ก ๋ฐํํฉ๋๋ค. ์ธ์์ ํ์
์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
def id (x : ฮฑ) : ฮฑ := x
Lean์ ๋ฐํ ํ์
์ ์ค์ค๋ก ๊ฒฐ์ ํ ์ ์์ต๋๋ค.
def id (x : ฮฑ) := x
ํ์ง๋ง ์ธ์ ํ์
์ ์๋ตํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
def id x := xFailed to infer type of binder `x`
์ผ๋ฐ์ ์ผ๋ก, "failed to infer"์ ๊ฐ์ ๋ฉ์์ง๋ ๋ฉํ๋ณ์๋ฅผ ์ธ๊ธํ๋ ๋ฉ์์ง๋ ๋ ๋ง์ ํ์
์ด๋
ธํ
์ด์
์ด ํ์ํ๋ค๋ ์ ํธ์ผ ์ ์์ต๋๋ค. ํนํ Lean์ ๋ฐฐ์ฐ๋ ๋์์๋ ๋๋ถ๋ถ์ ํ์
์ ๋ช
์์ ์ผ๋ก ์ ๊ณตํ๋ ๊ฒ์ด ์ ์ฉํฉ๋๋ค.
1.7.5. ๋์ ๋งค์นญ
ํจํด ๋งค์นญ ํํ์์ ํจํด ๋งค์นญ ์ ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ฌ๋ฌ ๊ฐ์ ํ ๋ฒ์ ๋งค์นญํ ์ ์์ต๋๋ค. ๊ฒ์ฌํ ํํ์๊ณผ ๊ทธ์ ๋์ํ๋ ํจํด ๋ชจ๋ ์ ์์ ์ฌ์ฉ๋ ๊ตฌ๋ฌธ๊ณผ ์ ์ฌํ๊ฒ ์ผํ๋ก ๊ตฌ๋ถํ์ฌ ์์ฑ๋ฉ๋๋ค. ๋ค์์ ๋์ ๋งค์นญ์ ์ฌ์ฉํ๋ ๋ฐฉ์์ drop์
๋๋ค.
def drop (n : Nat) (xs : List ฮฑ) : List ฮฑ := match n, xs with | Nat.zero, ys => ys | _, [] => [] | Nat.succ n , y :: ys => drop n ys
๋์ ๋งค์นญ์ ์์ ๋ํ ๋งค์นญ๊ณผ ์ ์ฌํ์ง๋ง, ์ค์ํ ์ฐจ์ด์ ์ด ์์ต๋๋ค. Lean์ ๋งค์นญ๋๋ ํํ์๊ณผ ํจํด ์ฌ์ด์ ์ฐ๊ฒฐ์ ์ถ์ ํ๋ฉฐ, ์ด ์ ๋ณด๋ ์ข
๋ฃ ๊ฒ์ฌ ๋ฐ ์ ์ ํ์
์ ๋ณด ์ ํ์ ๊ฐ์ ๋ชฉ์ ์ ์ฌ์ฉ๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก, ์์ ๋งค์นญํ๋ ๋ฐฉ์์ sameLength์ ์ข
๋ฃ ๊ฒ์ฌ๊ธฐ์ ์ํด ๊ฑฐ๋ถ๋ฉ๋๋ค. ์๋ํ๋ฉด xs์ x :: xs' ์ฌ์ด์ ์ฐ๊ฒฐ์ด ์ค๊ฐ์ ์๋ ์์ ์ํด ๊ฐ๋ ค์ง๊ธฐ ๋๋ฌธ์
๋๋ค.
def sameLength (xs : List ฮฑ) (ys : List ฮฒ) : Bool := match (xs, ys) with | ([], []) => true | (x :: xs', y :: ys') => sameLength xs' ys' | _ => falsefail to show termination for sameLengthwith errorsfailed to infer structural recursion:Not considering parameter ฮฑ of sameLength: it is unchanged in the recursive callsNot considering parameter ฮฒ of sameLength: it is unchanged in the recursive callsCannot use parameter xs: failed to eliminate recursive application sameLength xs' ys'Cannot use parameter ys: failed to eliminate recursive application sameLength xs' ys'Could not find a decreasing measure.The basic measures relate at each recursive call as follows:(<, โค, =: relation proved, ? all proofs failed, _: no proof attempted) xs ys1) 1816:28-46 ? ?Please use `termination_by` to specify a decreasing measure.
๋ ๋ฆฌ์คํธ๋ฅผ ๋์์ ๋งค์นญํ๋ ๊ฒ์ ํ์ฉ๋ฉ๋๋ค.
def sameLength (xs : List ฮฑ) (ys : List ฮฒ) : Bool := match xs, ys with | [], [] => true | x :: xs', y :: ys' => sameLength xs' ys' | _, _ => false
1.7.6. ์์ฐ์ ํจํด
๋ฐ์ดํฐ ํ์
๊ณผ ํจํด์ ๋ํ ์น์
์์, even์ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์์ต๋๋ค:
def even (n : Nat) : Bool := match n with | Nat.zero => true | Nat.succ k => not (even k)
List.cons์ List.nil์ ์ง์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ๋ฆฌ์คํธ ํจํด์ ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋๋ ํน๋ณํ ๊ตฌ๋ฌธ์ด ์๋ ๊ฒ์ฒ๋ผ, ์์ฐ์๋ ๋ฆฌํฐ๋ด ์ซ์์ +๋ฅผ ์ฌ์ฉํ์ฌ ๋งค์นญํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, even์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ ์๋ ์์ต๋๋ค:
def even : Nat โ Bool | 0 => true | n + 1 => not (even n)
์ด ํ๊ธฐ๋ฒ์์ + ํจํด์ ์ธ์๋ค์ ์๋ก ๋ค๋ฅธ ์ญํ ์ ํฉ๋๋ค. ๋ด๋ถ์ ์ผ๋ก ์ผ์ชฝ ์ธ์(์์ n)๋ ์ฌ๋ฌ Nat.succ ํจํด์ ์ธ์๊ฐ ๋๊ณ , ์ค๋ฅธ์ชฝ ์ธ์(์์ 1)๋ ํจํด์ ๊ฐ์ Nat.succ์ ๊ฐ์๋ฅผ ๊ฒฐ์ ํฉ๋๋ค. Nat์ 2๋ก ๋๋๊ณ ๋๋จธ์ง๋ฅผ ๋ฒ๋ฆฌ๋ halve์ ๋ช
์์ ํจํด์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
def halve : Nat โ Nat | Nat.zero => 0 | Nat.succ Nat.zero => 0 | Nat.succ (Nat.succ n) => halve n + 1
์ด๋ ์ซ์ ๋ฆฌํฐ๋ด๊ณผ +๋ก ๋์ฒด๋ ์ ์์ต๋๋ค:
def halve : Nat โ Nat | 0 => 0 | 1 => 0 | n + 2 => halve n + 1
๋ด๋ถ์ ์ผ๋ก ๋ ์ ์๋ ์์ ํ ๋์ผํฉ๋๋ค. ๊ธฐ์ตํ์ธ์: halve n + 1์ halve (n + 1)์ด ์๋๋ผ (halve n) + 1๊ณผ ๋์ผํฉ๋๋ค.
์ด ๊ตฌ๋ฌธ์ ์ฌ์ฉํ ๋, +์ ๋ ๋ฒ์งธ ์ธ์๋ ํญ์ ๋ฆฌํฐ๋ด Nat์ด์ด์ผ ํฉ๋๋ค. ๋ง์
์ ๊ตํ ๋ฒ์น์ด ์ฑ๋ฆฝํ์ง๋ง, ํจํด์์ ์ธ์์ ์์๋ฅผ ๋ฐ๊พธ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค:
def halve : Nat โ Nat | 0 => 0 | 1 => 0 | 2 + n => halve n + 1Invalid pattern(s): `n` is an explicit pattern variable, but it only occurs in positions that are inaccessible to pattern matching: .(Nat.add 2 n)
์ด ์ ์ฝ ๋๋ถ์ Lean์ ํจํด์์ ์ฌ์ฉ๋๋ ๋ชจ๋ + ํ๊ธฐ๋ฒ์ ๋ด๋ถ์ ์ธ Nat.succ ์ฌ์ฉ์ผ๋ก ๋ณํํ ์ ์์ผ๋ฉฐ, ์ด๋ ์ธ์ด์ ๋ด๋ถ๋ฅผ ๋ ๋จ์ํ๊ฒ ์ ์งํด ์ค๋๋ค.
1.7.7. ์ต๋ช
ํจ์
Lean์ ํจ์๋ ์ต์์ ์์ค์์ ์ ์๋ ํ์๊ฐ ์์ต๋๋ค. ํํ์์ผ๋ก์์ ํจ์๋ fun ๊ตฌ๋ฌธ์ ์ฌ์ฉํ์ฌ ์์ฑ๋ฉ๋๋ค. ํจ์ ํํ์์ fun ํค์๋๋ก ์์ํ๋ฉฐ, ํ๋ ์ด์์ ๋งค๊ฐ๋ณ์๊ฐ ๋ค๋ฐ๋ฅด๊ณ , =>๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐํ ํํ์๊ณผ ๊ตฌ๋ถ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ซ์์ 1์ ๋ํ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค:
#check fun x => x + 1fun x => x + 1 : Nat โ Nat
ํ์
์ฃผ์์ def์์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๊ดํธ์ ์ฝ๋ก ์ ์ฌ์ฉํ์ฌ ์์ฑ๋ฉ๋๋ค:
#check fun (x : Int) => x + 1fun x => x + 1 : Int โ Int
๋ง์ฐฌ๊ฐ์ง๋ก, ์์์ ๋งค๊ฐ๋ณ์๋ ์ค๊ดํธ๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑํ ์ ์์ต๋๋ค:
#check fun {ฮฑ : Type} (x : ฮฑ) => xfun {ฮฑ} x => x : {ฮฑ : Type} โ ฮฑ โ ฮฑ
์ด๋ฌํ ์คํ์ผ์ ์ต๋ช
ํจ์ ํํ์์ ์ข
์ข
๋๋ค ํํ์์ด๋ผ๊ณ ๋ถ๋ฆฝ๋๋ค. ์ด๋ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ ์ํ์ ์ค๋ช
์์ ์ฌ์ฉ๋๋ ์ผ๋ฐ์ ์ธ ํ๊ธฐ๋ฒ์ด Lean์ fun ํค์๋ ์๋ฆฌ์ ๊ทธ๋ฆฌ์ค ๋ฌธ์ ฮป(๋๋ค)๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋๋ค. Lean์ด fun ๋์ ฮป๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ฉํ๊ธด ํ์ง๋ง, fun์ ์ฐ๋ ๊ฒ์ด ๊ฐ์ฅ ์ผ๋ฐ์ ์
๋๋ค.
์ต๋ช
ํจ์๋ def์์ ์ฌ์ฉ๋๋ ๋ค์ค ํจํด ์คํ์ผ๋ ์ง์ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์์ฐ์์ ์ด์ ์๋ฅผ (์กด์ฌํ๋ ๊ฒฝ์ฐ) ๋ฐํํ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค:
#check fun | 0 => none | n + 1 => some nfun x => match x with | 0 => none | n.succ => some n : Nat โ Option Nat
Lean์ด ํจ์๋ฅผ ์ค๋ช
ํ ๋ ์ด๋ฆ ์๋ ์ธ์์ match ํํ์์ ์ฌ์ฉํ๋ค๋ ์ ์ ์ ์ํ์ธ์. Lean์ ํธ๋ฆฌํ ๊ตฌ๋ฌธ์ ์ถ์ฝํ ์ค ๋ค์๋ ๋ด๋ถ์ ์ผ๋ก ๋ ๊ฐ๋จํ ๊ตฌ๋ฌธ์ผ๋ก ํ์ฅ๋๋ฉฐ, ๋๋ก๋ ์ด๋ฌํ ์ถ์ํ๊ฐ ๋๋ฌ๋๊ธฐ๋ ํฉ๋๋ค.
์ธ์๋ฅผ ๋ฐ๋ def๋ฅผ ์ฌ์ฉํ ์ ์๋ ํจ์ ํํ์์ผ๋ก ๋ค์ ์์ฑ๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ธ์๋ฅผ ๋ ๋ฐฐ๋ก ๋ง๋๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค:
def double : Nat โ Nat := fun | 0 => 0 | k + 1 => double k + 2
fun x => x + 1๊ณผ ๊ฐ์ด ์ต๋ช
ํจ์๊ฐ ๋งค์ฐ ๊ฐ๋จํ ๋, ํจ์๋ฅผ ๋ง๋๋ ๊ตฌ๋ฌธ์ ์๋นํ ์ฅํฉํ ์ ์์ต๋๋ค. ์ด ํน์ ์์์๋ ํจ์๋ฅผ ๋์
ํ๋ ๋ฐ 6๊ฐ์ ๊ณต๋ฐฑ์ด ์๋ ๋ฌธ์๊ฐ ์ฌ์ฉ๋์๊ณ , ๋ณธ๋ฌธ์ 3๊ฐ์ ๊ณต๋ฐฑ์ด ์๋ ๋ฌธ์๋ก๋ง ๊ตฌ์ฑ๋ฉ๋๋ค. ์ด๋ฌํ ๊ฐ๋จํ ๊ฒฝ์ฐ๋ฅผ ์ํด Lean์ ์ถ์ฝํ์ ์ ๊ณตํฉ๋๋ค. ๊ดํธ๋ก ๋๋ฌ์ธ์ธ ํํ์์์ ยท(MIDDLE DOT)๋ ๋งค๊ฐ๋ณ์๋ฅผ ๋ํ๋ผ ์ ์์ผ๋ฉฐ, ๊ดํธ ์์ ํํ์์ ํจ์์ ๋ณธ๋ฌธ์ด ๋ฉ๋๋ค. ์ด ํน์ ํจ์๋ (ยท + 1)๋ก๋ ์์ฑํ ์ ์์ต๋๋ค.
ยท์ ํญ์ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ดํธ ์ธํธ๋ก๋ถํฐ ํจ์๋ฅผ ๋ง๋ญ๋๋ค. ์๋ฅผ ๋ค์ด, (ยท + 5, 3)์ ์ซ์ ์์ ๋ฐํํ๋ ํจ์์ธ ๋ฐ๋ฉด, ((ยท + 5), 3)์ ํจ์์ ์ซ์๋ก ์ด๋ฃจ์ด์ง ์์
๋๋ค. ์ฌ๋ฌ ๊ฐ์ ์ ์ด ์ฌ์ฉ๋๋ฉด ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ ์์๋ก ๋งค๊ฐ๋ณ์๊ฐ ๋ฉ๋๋ค:
(ยท , ยท) 1 2(1, ยท) 2(1, 2)
์ต๋ช
ํจ์๋ def๋ let์ ์ฌ์ฉํ์ฌ ์ ์๋ ํจ์์ ์ ํํ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์ ์ฉ๋ ์ ์์ต๋๋ค. #eval (fun x => x + x) 5 ๋ช
๋ น์ด๋ ๋ค์์ ๊ฒฐ๊ณผ๋ก ๋
๋๋ค:
10
๋ฐ๋ฉด #eval (ยท * 2) 5๋ ๋ค์์ ๊ฒฐ๊ณผ๋ก ๋
๋๋ค:
10
1.7.8. ๋ค์์คํ์ด์ค
Lean์ ๊ฐ ์ด๋ฆ์ ์ด๋ฆ์ ๋ชจ์์ธ ๋ค์์คํ์ด์ค ์์ ์กด์ฌํฉ๋๋ค. ์ด๋ฆ์ .์ ์ฌ์ฉํ์ฌ ๋ค์์คํ์ด์ค์ ๋ฐฐ์น๋๋ฏ๋ก, List.map์ List ๋ค์์คํ์ด์ค์ ์๋ map์ด๋ผ๋ ์ด๋ฆ์
๋๋ค. ์๋ก ๋ค๋ฅธ ๋ค์์คํ์ด์ค์ ์๋ ์ด๋ฆ๋ค์ ๋ค๋ฅธ ๋ถ๋ถ์ด ๋์ผํ๋๋ผ๋ ์๋ก ์ถฉ๋ํ์ง ์์ต๋๋ค. ์ด๋ List.map๊ณผ Array.map์ด ๋ค๋ฅธ ์ด๋ฆ์์ ์๋ฏธํฉ๋๋ค. ๋ค์์คํ์ด์ค๋ ์ค์ฒฉ๋ ์ ์์ผ๋ฏ๋ก, Project.Frontend.User.loginTime์ ์ค์ฒฉ๋ Project.Frontend.User ๋ค์์คํ์ด์ค์ ์๋ loginTime์ด๋ผ๋ ์ด๋ฆ์
๋๋ค.
์ด๋ฆ์ ๋ค์์คํ์ด์ค ๋ด์์ ์ง์ ์ ์๋ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, double์ด๋ผ๋ ์ด๋ฆ์ Nat ๋ค์์คํ์ด์ค์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ ์ ์์ต๋๋ค:
def Nat.double (x : Nat) : Nat := x + x
Nat์ ํ์
์ ์ด๋ฆ์ด๊ธฐ๋ ํ๋ฏ๋ก, Nat ํ์
์ ํํ์์ Nat.double์ ํธ์ถํ๊ธฐ ์ํด ์ ํ๊ธฐ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค:
#eval (4 : Nat).double8
๋ค์์คํ์ด์ค์ ์ง์ ์ด๋ฆ์ ์ ์ํ๋ ๊ฒ ์ธ์๋, namespace์ end ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ์ผ๋ จ์ ์ ์ธ๋ค์ ๋ค์์คํ์ด์ค์ ๋ฐฐ์นํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์์ NewNamespace๋ผ๋ ๋ค์์คํ์ด์ค์ triple๊ณผ quadruple์ ์ ์ํฉ๋๋ค:
namespace NewNamespacedef triple (x : Nat) : Nat := 3 * xdef quadruple (x : Nat) : Nat := 2 * x + 2 * xend NewNamespace
์ด๋ค์ ์ฐธ์กฐํ๋ ค๋ฉด ์ด๋ฆ ์์ NewNamespace.๋ฅผ ๋ถ์
๋๋ค:
#check NewNamespace.tripleNewNamespace.triple (x : Nat) : Nat#check NewNamespace.quadrupleNewNamespace.quadruple (x : Nat) : Nat
๋ค์์คํ์ด์ค๋ openํ ์ ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋ค์์คํ์ด์ค ์์ ์ด๋ฆ๋ค์ ๋ช
์์ ์ธ ํ์ ์ ์์ด ์ฌ์ฉํ ์ ์์ต๋๋ค. ํํ์ ์์ open MyNamespace in์ ์์ฑํ๋ฉด MyNamespace์ ๋ด์ฉ์ด ํด๋น ํํ์์์ ์ฌ์ฉ ๊ฐ๋ฅํด์ง๋๋ค. ์๋ฅผ ๋ค์ด, timesTwelve๋ NewNamespace๋ฅผ ์ฐ ํ์ quadruple๊ณผ triple์ ๋ชจ๋ ์ฌ์ฉํฉ๋๋ค:
def timesTwelve (x : Nat) := open NewNamespace in quadruple (triple x)
๋ค์์คํ์ด์ค๋ ๋ช
๋ น์ด ์์์๋ ์ด ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๋จ์ผ ํํ์๋ฟ๋ง ์๋๋ผ ๋ช
๋ น์ด์ ๋ชจ๋ ๋ถ๋ถ์์ ๋ค์์คํ์ด์ค์ ๋ด์ฉ์ ์ฐธ์กฐํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ๋ช
๋ น์ด ์์ open ... in์ ๋ฐฐ์นํฉ๋๋ค.
open NewNamespace in#check quadrupleNewNamespace.quadruple (x : Nat) : Nat
ํจ์ ์๊ทธ๋์ฒ๋ ์ด๋ฆ์ ์ ์ฒด ๋ค์์คํ์ด์ค๋ฅผ ๋ณด์ฌ์ค๋๋ค. ๋ค์์คํ์ด์ค๋ ํ์ผ์ ๋๋จธ์ง ๋ถ๋ถ์ ๋ํด ์ดํ์ ๋ชจ๋ ๋ช
๋ น์ด์ ๋ํด ์ถ๊ฐ์ ์ผ๋ก ์ด๋ฆด ์๋ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ์ต์์ ์์ค์์ open์ ์ฌ์ฉํ ๋ in์ ์๋ตํ๋ฉด ๋ฉ๋๋ค.
1.7.9. if let
ํฉ ํ์
์ ๊ฐ๋ ๊ฐ์ ์ฌ์ฉํ ๋, ์ข
์ข
๋จ ํ๋์ ์์ฑ์์๋ง ๊ด์ฌ์ด ์๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋งํฌ๋ค์ด ์ธ๋ผ์ธ ์์์ ์ผ๋ถ๋ฅผ ๋ํ๋ด๋ ๋ค์ ํ์
์ด ์ฃผ์ด์ก์ ๋:
inductive Inline : Type where | lineBreak | string : String โ Inline | emph : Inline โ Inline | strong : Inline โ Inline
๋ฌธ์์ด ์์๋ฅผ ์ธ์ํ๊ณ ๊ทธ ๋ด์ฉ์ ์ถ์ถํ๋ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค:
def Inline.string? (inline : Inline) : Option String := match inline with | Inline.string s => some s | _ => none
์ด ํจ์์ ๋ณธ๋ฌธ์ ์์ฑํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ if์ let์ ํจ๊ป ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค:
def Inline.string? (inline : Inline) : Option String := if let Inline.string s := inline then some s else none
์ด๊ฒ์ ํจํด ๋งค์นญ let ๊ตฌ๋ฌธ๊ณผ ๋งค์ฐ ์ ์ฌํฉ๋๋ค. ์ฐจ์ด์ ์ else ๊ฒฝ์ฐ์ ๋์ฒด ๋ฐฉ์์ด ์ ๊ณต๋๊ธฐ ๋๋ฌธ์ ํฉ ํ์
๊ณผ ํจ๊ป ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์
๋๋ค. ์ผ๋ถ ๋ฌธ๋งฅ์์๋ match ๋์ if let์ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ๋ ์ฝ๊ธฐ ์ฝ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
1.7.10. ์์น ๊ธฐ๋ฐ ๊ตฌ์กฐ์ฒด ์ธ์
๊ตฌ์กฐ์ฒด์ ๋ํ ์น์
์์๋ ๊ตฌ์กฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ์ํฉ๋๋ค:
Point.mk 1 2 ๊ฐ์ ์์ฑ์ ์ง์ ํธ์ถ.
{ x := 1, y := 2 } ๊ฐ์ ์ค๊ดํธ ํ๊ธฐ๋ฒ.
์ด๋ค ๋ฌธ๋งฅ์์๋ ์์ฑ์๋ฅผ ์ง์ ๋ช
๋ช
ํ์ง ์๊ณ , ์ด๋ฆ ๋์ ์์น์ ๋ฐ๋ผ ์ธ์๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด ํธ๋ฆฌํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ค์ํ ์ ์ฌํ ๊ตฌ์กฐ์ฒด ํ์
์ ์ ์ํ๋ฉด ๋๋ฉ์ธ ๊ฐ๋
์ ๋ถ๋ฆฌํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ง๋ง, ์ฝ๋๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ์ฝ๋ ๋ฐฉ์์ ๊ฐ๊ฐ์ ๋ณธ์ง์ ์ผ๋ก ํํ๋ก ์ทจ๊ธํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๋ฌธ๋งฅ์์๋ ์ธ์๋ฅผ ๊บพ์ ๊ดํธ โจ์ โฉ๋ก ๋ฌถ์ ์ ์์ต๋๋ค. Point๋ โจ1, 2โฉ๋ก ์์ฑํ ์ ์์ต๋๋ค. ์กฐ์ฌํ์ธ์! ์ด ๊ดํธ๋ค์ ๋ถ๋ฑํธ <์ >์ฒ๋ผ ๋ณด์ด์ง๋ง ๋ค๋ฅธ ๋ฌธ์์
๋๋ค. ๊ฐ๊ฐ \<์ \>๋ฅผ ์ฌ์ฉํ์ฌ ์
๋ ฅํ ์ ์์ต๋๋ค.
์ด๋ฆ ์๋ ์์ฑ์ ์ธ์๋ฅผ ์ํ ์ค๊ดํธ ํ๊ธฐ๋ฒ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ด ์์น ๊ธฐ๋ฐ ๊ตฌ๋ฌธ์ Lean์ด ํ์
์ฃผ์์ด๋ ํ๋ก๊ทธ๋จ์ ๋ค๋ฅธ ํ์
์ ๋ณด๋ก๋ถํฐ ๊ตฌ์กฐ์ฒด์ ํ์
์ ๊ฒฐ์ ํ ์ ์๋ ๋ฌธ๋งฅ์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, #eval โจ1, 2โฉ๋ ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค:
Invalid `โจ...โฉ` notation: The expected type of this term could not be determined
์ด ์ค๋ฅ๋ ์ฌ์ฉ ๊ฐ๋ฅํ ํ์
์ ๋ณด๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํฉ๋๋ค. #eval (โจ1, 2โฉ : Point)์ ๊ฐ์ด ์ฃผ์์ ์ถ๊ฐํ๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋ฉ๋๋ค:
{ x := 1.000000, y := 2.000000 }
1.7.11. ๋ฌธ์์ด ๋ณด๊ฐ
Lean์์ ๋ฌธ์์ด ์์ s!๋ฅผ ๋ถ์ด๋ฉด ๋ณด๊ฐ์ด ํ์ฑํ๋์ด, ๋ฌธ์์ด ์์ ์ค๊ดํธ์ ํฌํจ๋ ํํ์์ด ๊ทธ ๊ฐ์ผ๋ก ๋์ฒด๋ฉ๋๋ค. ์ด๋ ํ์ด์ฌ์ f-string์ด๋ C# ์ $-์ ๋์ฌ ๋ฌธ์์ด๊ณผ ์ ์ฌํฉ๋๋ค. ์๋ฅผ ๋ค์ด,
#eval s!"three fives is {NewNamespace.triple 5}"
๋ ๋ค์์ ์ถ๋ ฅํฉ๋๋ค:
"three fives is 15"
๋ชจ๋ ํํ์์ด ๋ฌธ์์ด์ ๋ณด๊ฐ๋ ์ ์๋ ๊ฒ์ ์๋๋๋ค. ์๋ฅผ ๋ค์ด, ํจ์๋ฅผ ๋ณด๊ฐํ๋ ค๊ณ ํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
#check s!"three fives is {NewNamespace.triple}"
๋ ๋ค์ ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค:
failed to synthesize ToString (Nat โ Nat)Hint: Additional diagnostic information may be available using the `set_option diagnostics true` command.
์ด๋ ํจ์๋ฅผ ๋ฌธ์์ด๋ก ๋ณํํ๋ ํ์ค์ ์ธ ๋ฐฉ๋ฒ์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ปดํ์ผ๋ฌ๊ฐ ๋ค์ํ ํ์
์ ํํ์ ํ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ํ์ํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช
ํ๋ ํ
์ด๋ธ์ ์ ์งํ๋ ๊ฒ์ฒ๋ผ, ๋ค์ํ ํ์
์ ๊ฐ์ ๋ฌธ์์ด๋ก ๋ณํํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช
ํ๋ ํ
์ด๋ธ์ ์ ์งํฉ๋๋ค. failed to synthesize instance๋ผ๋ ๋ฉ์์ง๋ Lean ์ปดํ์ผ๋ฌ๊ฐ ์ฃผ์ด์ง ํ์
์ ๋ํด ์ด ํ
์ด๋ธ์์ ํญ๋ชฉ์ ์ฐพ์ง ๋ชปํ์์ ์๋ฏธํฉ๋๋ค. ํ์
ํด๋์ค์ ๋ํ ์ฅ์์๋ ํ
์ด๋ธ์ ์ ํญ๋ชฉ์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ํฌํจํ์ฌ ์ด ๋ฉ์ปค๋์ฆ์ ๋ ์์ธํ ์ค๋ช
ํฉ๋๋ค.
1.8. ์์ฝ
1.8.1. ํํ์ ํ๊ฐ
Lean์์ ๊ณ์ฐ์ ํํ์์ด ํ๊ฐ๋ ๋ ๋ฐ์ํฉ๋๋ค. ์ด๋ ์ผ๋ฐ์ ์ธ ์ํ ํํ์์ ๊ท์น์ ๋ฐ๋ฆ
๋๋ค. ์ฆ, ์ ์ฒด ํํ์์ด ๊ฐ์ด ๋ ๋๊น์ง ํ์ ํํ์์ ์ผ๋ฐ์ ์ธ ์ฐ์ฐ ์์์ ๋ฐ๋ผ ํด๋น ๊ฐ์ผ๋ก ๋์ฒด๋ฉ๋๋ค. if๋ match๋ฅผ ํ๊ฐํ ๋, ์กฐ๊ฑด์ด๋ match ๋์์ ๊ฐ์ด ๋ฐ๊ฒฌ๋ ๋๊น์ง ๋ถ๊ธฐ ๋ด์ ํํ์์ ํ๊ฐ๋์ง ์์ต๋๋ค.
๋ณ์๋ ์ผ๋จ ๊ฐ์ ํ ๋น๋ฐ์ผ๋ฉด ์ ๋ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. ์ํ๊ณผ ์ ์ฌํ์ง๋ง ๋๋ถ๋ถ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์๋ ๋ฌ๋ฆฌ, Lean์ ๋ณ์๋ ์๋ก์ด ๊ฐ์ ์ธ ์ ์๋ ์ฃผ์๋ผ๊ธฐ๋ณด๋ค๋ ๋จ์ํ ๊ฐ์ ์ํ ์๋ฆฌ ํ์์์
๋๋ค. ๋ณ์์ ๊ฐ์ def๋ฅผ ์ฌ์ฉํ ์ ์ญ ์ ์, let์ ์ฌ์ฉํ ์ง์ญ ์ ์, ํจ์์ ๋ช
๋ช
๋ ์ธ์ ๋๋ ํจํด ๋งค์นญ์์ ์ฌ ์ ์์ต๋๋ค.
1.8.2. ํจ์
Lean์์ ํจ์๋ ์ผ๊ธ ๊ฐ์
๋๋ค. ์ฆ, ๋ค๋ฅธ ํจ์์ ์ธ์๋ก ์ ๋ฌ๋๊ฑฐ๋, ๋ณ์์ ์ ์ฅ๋๊ฑฐ๋, ๋ค๋ฅธ ๊ฐ์ฒ๋ผ ์ฌ์ฉ๋ ์ ์์ต๋๋ค. ๋ชจ๋ Lean ํจ์๋ ์ ํํ ํ๋์ ์ธ์๋ฅผ ๋ฐ์ต๋๋ค. ๋ ์ด์์ ์ธ์๋ฅผ ๋ฐ๋ ํจ์๋ฅผ ์ธ์ฝ๋ฉํ๊ธฐ ์ํด Lean์ ์ปค๋ง(currying)์ด๋ผ๋ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋๋ฐ, ์ฒซ ๋ฒ์งธ ์ธ์๋ฅผ ์ ๊ณตํ๋ฉด ๋๋จธ์ง ์ธ์๋ฅผ ๊ธฐ๋ํ๋ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค. ์ธ์๋ฅผ ๋ฐ์ง ์๋ ํจ์๋ฅผ ์ธ์ฝ๋ฉํ๊ธฐ ์ํด Lean์ ๊ฐ๋ฅํ ๊ฐ์ฅ ์ ๋ณด๊ฐ ์ ์ ์ธ์์ธ Unit ํ์
์ ์ฌ์ฉํฉ๋๋ค.
ํจ์๋ฅผ ๋ง๋๋ ์ฃผ์ ๋ฐฉ๋ฒ์ ์ธ ๊ฐ์ง๊ฐ ์์ต๋๋ค.
์ต๋ช
ํจ์๋ fun์ ์ฌ์ฉํ์ฌ ์์ฑ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด, Point์ ํ๋๋ฅผ ๋ฐ๊พธ๋ ํจ์๋ fun (point : Point) => { x := point.y, y := point.x : Point }์ ๊ฐ์ด ์์ฑํ ์ ์์ต๋๋ค.
๋งค์ฐ ๊ฐ๋จํ ์ต๋ช
ํจ์๋ ๊ดํธ ์์ ํ๋ ์ด์์ ยท์ ๋ฐฐ์นํ์ฌ ์์ฑ๋ฉ๋๋ค. ๊ฐ ๊ฐ์ด๋ฐ ์ ์ ํจ์์ ์ธ์๊ฐ ๋๊ณ , ๊ดํธ๋ ํจ์์ ๋ณธ๋ฌธ์ ๊ตฌ๋ถํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ์ธ์์์ 1์ ๋นผ๋ ํจ์๋ fun x => x - 1 ๋์ (ยท - 1)๋ก ์์ฑํ ์ ์์ต๋๋ค.
ํจ์๋ ์ธ์ ๋ชฉ๋ก์ ์ถ๊ฐํ๊ฑฐ๋ ํจํด ๋งค์นญ ํ๊ธฐ๋ฒ์ ์ฌ์ฉํ์ฌ def ๋๋ let์ผ๋ก ์ ์ํ ์ ์์ต๋๋ค.
1.8.3. ํ์
Lean์ ๋ชจ๋ ํํ์์ ํ์
์ด ์๋์ง ํ์ธํฉ๋๋ค. Int, Point, {ฮฑ : Type} โ Nat โ ฮฑ โ List ฮฑ, ๊ทธ๋ฆฌ๊ณ Option (String โ (Nat ร String))๊ณผ ๊ฐ์ ํ์
์ ํํ์์ ๋ํด ์ต์ข
์ ์ผ๋ก ๋ฐ๊ฒฌ๋ ์ ์๋ ๊ฐ์ ์ค๋ช
ํฉ๋๋ค. ๋ค๋ฅธ ์ธ์ด์ ๋ง์ฐฌ๊ฐ์ง๋ก Lean์ ํ์
์ Lean ์ปดํ์ผ๋ฌ์ ์ํด ํ์ธ๋๋ ํ๋ก๊ทธ๋จ์ ๊ฐ๋ฒผ์ด ๋ช
์ธ๋ฅผ ํํํ ์ ์์ด, ํน์ ์ข
๋ฅ์ ๋จ์ ํ
์คํธ ํ์์ฑ์ ์์ ์ค๋๋ค. ๋๋ถ๋ถ์ ์ธ์ด์ ๋ฌ๋ฆฌ, Lean์ ํ์
์ ์์์ ์ํ๋ ํํํ ์ ์์ด ํ๋ก๊ทธ๋๋ฐ๊ณผ ์ ๋ฆฌ ์ฆ๋ช
์ ์ธ๊ณ๋ฅผ ํตํฉํฉ๋๋ค. ์ด ์ฑ
์์๋ ์ ๋ฆฌ ์ฆ๋ช
์ ์ํด Lean์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ถ๋ถ ๋ค๋ฃจ์ง ์์ง๋ง, Theorem Proving in Lean 4์์ ์ด ์ฃผ์ ์ ๋ํ ๋ ๋ง์ ์ ๋ณด๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.
์ผ๋ถ ํํ์์๋ ์ฌ๋ฌ ํ์
์ด ์ฃผ์ด์ง ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, 3์ Int ๋๋ Nat๊ฐ ๋ ์ ์์ต๋๋ค. Lean์์๋ ์ด๋ฅผ ๊ฐ์ ๊ฒ์ ๋ํ ๋ ๊ฐ์ง ๋ค๋ฅธ ํ์
์ด ์๋๋ผ, ์ฐ์ฐํ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์์ฑ๋, ํ๋๋ Nat ํ์
์ด๊ณ ๋ค๋ฅธ ํ๋๋ Int ํ์
์ธ ๋ ๊ฐ์ ๋ณ๋ ํํ์์ผ๋ก ์ดํดํด์ผ ํฉ๋๋ค.
Lean์ ๋๋๋ก ํ์
์ ์๋์ผ๋ก ๊ฒฐ์ ํ ์ ์์ง๋ง, ์ข
์ข
์ฌ์ฉ์๊ฐ ํ์
์ ์ ๊ณตํด์ผ ํฉ๋๋ค. ์ด๋ Lean์ ํ์
์์คํ
์ด ๋งค์ฐ ํํ๋ ฅ์ด ํ๋ถํ๊ธฐ ๋๋ฌธ์
๋๋ค. Lean์ด ํ์
์ ์ฐพ์ ์ ์๋๋ผ๋ ์ํ๋ ํ์
์ ์ฐพ์ง ๋ชปํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด 3์ Int๋ก ์ฌ์ฉ๋ ์๋์์ ์ ์์ง๋ง, ์ถ๊ฐ์ ์ธ ์ ์ฝ ์กฐ๊ฑด์ด ์๋ค๋ฉด Lean์ Nat ํ์
์ ๋ถ์ฌํ ๊ฒ์
๋๋ค. ์ผ๋ฐ์ ์ผ๋ก, ๋๋ถ๋ถ์ ํ์
์ ๋ช
์์ ์ผ๋ก ์์ฑํ๊ณ , ์์ฃผ ๋ช
๋ฐฑํ ํ์
๋ง Lean์ด ์ฑ์ฐ๋๋ก ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ Lean์ ์ค๋ฅ ๋ฉ์์ง๋ฅผ ๊ฐ์ ํ๊ณ ํ๋ก๊ทธ๋๋จธ์ ์๋๋ฅผ ๋ ๋ช
ํํ๊ฒ ํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
์ผ๋ถ ํจ์๋ ๋ฐ์ดํฐ ํ์
์ ํ์
์ ์ธ์๋ก ๋ฐ์ต๋๋ค. ์ด๋ฐ ํน์ฑ์ ๋คํ์ฑ(polymorphic)์ด๋ผ๊ณ ํฉ๋๋ค. ๋คํ์ฑ์ ๋ฆฌ์คํธ์ ํญ๋ชฉ ํ์
์ ์๊ด์์ด ๋ฆฌ์คํธ์ ๊ธธ์ด๋ฅผ ๊ณ์ฐํ๋ ๊ฒ๊ณผ ๊ฐ์ ํ๋ก๊ทธ๋จ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. Lean์์๋ ํ์
์ด ์ผ๊ธ ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ๋คํ์ฑ์ ํน๋ณํ ๊ตฌ๋ฌธ์ ํ์๋ก ํ์ง ์์ผ๋ฏ๋ก, ํ์
์ ๋ค๋ฅธ ์ธ์์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ ๋ฌ๋ฉ๋๋ค. ํจ์ ํ์
์์ ์ธ์์ ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋์ค์ ํ์
์์ ๊ทธ ์ด๋ฆ์ ์ฐธ์กฐํ ์ ์์ผ๋ฉฐ, ํจ์๊ฐ ์ธ์์ ์ ์ฉ๋ ๋ ๊ฒฐ๊ณผ ํญ์ ํ์
์ ์ธ์์ ์ด๋ฆ์ด ์ ์ฉ๋ ์ค์ ๊ฐ์ผ๋ก ๋์ฒด๋์ด ์ฐพ์์ง๋๋ค.
1.8.4. ๊ตฌ์กฐ์ฒด์ ๊ท๋ฉ์ ํ์
structure ๋๋ inductive ๊ธฐ๋ฅ์ ์ฌ์ฉํ์ฌ Lean์ ์๋ก์ด ๋ฐ์ดํฐ ํ์
์ ๋์
ํ ์ ์์ต๋๋ค. ์ด ์๋ก์ด ํ์
์ ์ ์๊ฐ ๋์ผํ๋๋ผ๋ ๋ค๋ฅธ ์ด๋ค ํ์
๊ณผ๋ ๋๋ฑํ๋ค๊ณ ๊ฐ์ฃผ๋์ง ์์ต๋๋ค. ๋ฐ์ดํฐ ํ์
์๋ ํด๋น ๊ฐ๋ค์ด ์์ฑ๋ ์ ์๋ ๋ฐฉ๋ฒ์ ์ค๋ช
ํ๋ ์์ฑ์๊ฐ ์์ผ๋ฉฐ, ๊ฐ ์์ฑ์๋ ์ฌ๋ฌ ๊ฐ์ ์ธ์๋ฅผ ๋ฐ์ต๋๋ค. Lean์ ์์ฑ์๋ ๊ฐ์ฒด ์งํฅ ์ธ์ด์ ์์ฑ์์ ๋ค๋ฆ
๋๋ค. Lean์ ์์ฑ์๋ ํ ๋น๋ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ๋ ๋ฅ๋์ ์ธ ์ฝ๋๊ฐ ์๋๋ผ, ๋ฐ์ดํฐ๋ฅผ ๋ด๊ณ ์๋ ๋นํ์ฑ ํ๋์
๋๋ค.
์ผ๋ฐ์ ์ผ๋ก structure๋ ๊ณฑ ํ์
(์ฆ, ์ฌ๋ฌ ์ธ์๋ฅผ ๋ฐ๋ ๋จ ํ๋์ ์์ฑ์๋ฅผ ๊ฐ์ง ํ์
)์ ๋์
ํ๋ ๋ฐ ์ฌ์ฉ๋๊ณ , inductive๋ ํฉ ํ์
(์ฆ, ์ฌ๋ฌ ๊ฐ์ ๊ณ ์ ํ ์์ฑ์๋ฅผ ๊ฐ์ง ํ์
)์ ๋์
ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. structure๋ก ์ ์๋ ๋ฐ์ดํฐ ํ์
์๋ ๊ฐ ํ๋์ ๋ํ ์ ๊ทผ์ ํจ์๊ฐ ํ๋์ฉ ์ ๊ณต๋ฉ๋๋ค. ๊ตฌ์กฐ์ฒด์ ๊ท๋ฉ์ ๋ฐ์ดํฐ ํ์
๋ชจ๋ ํจํด ๋งค์นญ์ผ๋ก ์๋น๋ ์ ์์ผ๋ฉฐ, ์ด๋ ํด๋น ์์ฑ์๋ฅผ ํธ์ถํ๋ ๋ฐ ์ฌ์ฉ๋ ๊ตฌ๋ฌธ์ ์ผ๋ถ๋ฅผ ์ฌ์ฉํ์ฌ ์์ฑ์ ๋ด๋ถ์ ์ ์ฅ๋ ๊ฐ์ ๋
ธ์ถํฉ๋๋ค. ํจํด ๋งค์นญ์ ๊ฐ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ์๋ ๊ฒ์ด ๊ณง ๊ทธ ๊ฐ์ ์๋นํ๋ ๋ฐฉ๋ฒ์ ์๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
1.8.5. ์ฌ๊ท
์ฌ๊ท์ ์ด๋ผ๋ ๋ง์ ์ ์๋๋ ์ด๋ฆ์ด ์ ์ ์์ฒด์์ ์ฌ์ฉ๋๋ ๊ฒ์ ๋ปํฉ๋๋ค. Lean์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์ผ ๋ฟ๋ง ์๋๋ผ ๋ํํ ์ ๋ฆฌ ์ฆ๋ช
๊ธฐ์ด๊ธฐ๋ ํ๋ฏ๋ก, ์ฌ๊ท์ ์ ์์๋ ํน์ ์ ํ์ด ์์ต๋๋ค. Lean์ ๋
ผ๋ฆฌ์ ์ธก๋ฉด์์ ์ํ ์ ์๋ ๋
ผ๋ฆฌ์ ๋น์ผ๊ด์ฑ์ ์ด๋ํ ์ ์์ต๋๋ค.
์ฌ๊ท์ ์ ์๊ฐ Lean์ ๋
ผ๋ฆฌ์ ์ธก๋ฉด์ ํผ์ํ์ง ์๋๋ก ํ๊ธฐ ์ํด, Lean์ ๋ชจ๋ ์ฌ๊ท ํจ์๊ฐ ์ด๋ค ์ธ์๋ก ํธ์ถ๋๋ ์ข
๋ฃ๋๋ค๋ ๊ฒ์ ์ฆ๋ช
ํ ์ ์์ด์ผ ํฉ๋๋ค. ์ค์ ๋ก๋ ์ด๋ ์ฌ๊ท ํธ์ถ์ด ๋ชจ๋ ์
๋ ฅ์ ๊ตฌ์กฐ์ ์ผ๋ก ๋ ์์ ๋ถ๋ถ์ ๋ํด ์ํ๋์ด ํญ์ ๊ธฐ๋ณธ ์ฌ๋ก(base case)๋ก์ ์งํ์ ๋ณด์ฅํ๊ฑฐ๋, ์ฌ์ฉ์๊ฐ ํจ์๊ฐ ํญ์ ์ข
๋ฃ๋๋ค๋ ๋ค๋ฅธ ์ฆ๊ฑฐ๋ฅผ ์ ๊ณตํด์ผ ํจ์ ์๋ฏธํฉ๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก, ์ฌ๊ท์ ๊ท๋ฉ์ ํ์
์ ํด๋น ํ์
์ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ๋ ์์ฑ์๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค. ์ด๋ ์ข
๋ฃ๋์ง ์๋ ํจ์๋ฅผ ์ธ์ฝ๋ฉํ ๊ฐ๋ฅ์ฑ์ด ์๊ธฐ ๋๋ฌธ์
๋๋ค.
hackers.pub ยท Hackers' Pub