์์ฃผ ๋ฉ์ง ํ์ค์ผ์ ๊ฐ์ด ๋ฐฐ์๋ณด์ #1
by JiwonDevHello Haskell!
์์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ ์, ํจ์ํ์ ๋๊ฐ์ธ ๋ ผ๋ฆฌํ์ Haskell Curry์ ์ด๋ฆ์ ๋น๋ฆฐ ๋ฉ์ง ์ธ์ด์ ๋๋ค.
์ฌ์ง์ด ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ฉ์ด ์ค์ Currying์ด๋ผ๋ ํํ์ด ์์ฃ . ์ด๊ฑฐ ์ ์ฌ๋ ์ด๋ฆ์์ ๊ฐ์ ธ์จ ์ฉ์ด์ ๋๋ค.
C์ธ์ด์ ๋น์ทํ ์ ์์์ 1990๋ ๋์ ์ถ๋ฐํ์์ง๋ง ๊ฐ๋ ๋ณด๋ฉด ์ด๋ฏธ ๋งํด์ ํ์ค์ผ ๊ฐ๋ฐ์๋ค์ด ๋ค ์์ด์ง ๊ฒ์ด ์๋๊น ์์ฌ๋๋ ๊ฑฐ๋ถ์ด๊ธ ์ ๋ฐ์ดํธ ์๋์ ๋ฉ์ธ ์ฝ๋ ์์ฑ๋ถํฐ ์ด๋ ค์ด ์ ์ ๋๊ฐ ๋ฌ๋ ์ปค๋ธ๋ ์ธ์ ๋ ๊ฐ๋ฐ ์ธ์ด ์ ์ ์จ ์์ ์ตํ์๊ถ์ ์๋คํฌ๊ณ ์์ต๋๋ค. ํ์ง๋ง ์์ธ๋ก ๋งค๋์์ธต์ด ๋ํฐ์ฐ๋ฉฐ 2020๋ ๋๊น์ง ๊พธ์คํ ์ ๋ฐ์ดํธ๋ฅผ ํด์ฃผ๊ณ ์์ฃ .
์ต๊ทผ ๋ค์ด์ Side-Effect ( ์ธ๋ถ ํ๊ฒฝ์ ๋ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ์ด ๋ฌ๋ผ์ง๋ ๊ฒฝ์ฐ )์ ์ ๊ฑฐ์ ๋ฉ๋ชจ๋ฆฌ์ ๋ณ์๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋์์ ๋
ผ๋ฆฌ์ ์ผ๋ก ์ ์ด ํจ์์ ์ฌ์ฌ์ฉ์ฑ๊ณผ ๊ฐ๋
์ฑ์ ๋์ด๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ฌ์ฉ์ด ๋ง์ด ๋์์ต๋๋ค. ๊ทธ๋์ ๋๋ถ๋ถ์ ๋ชจ๋ํ ์ธ์ด๋ค์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํด์ฃผ๊ณ ์์ฃ . ๊ทธ๋๋ ํ์ค์ผ์ ์์๋๋ค.
ํ์ง๋ง ์ง๊ธ ์ด ๊ธ์ ์ฝ๊ณ ์๋ค๋ ๊ฑด ์ด์ฐ๋์๊ฑด ํ์ค์ผ์ ๋ฐฐ์ฐ๊ณ ์ถ๋ค๋ ๋ง์์ด ์๋ค๋ ๊ฑฐ๊ฒ ์ฃ .
ํจ๊ป ํ์ค์ผ์ ๋ํด ์์๋ด ์๋ค.
Haskell 3์ค ์์ฝ
- ์ง์ฐ๋ ๊ณ์ฐ ํ๊ฐ(lazy evaluation), ์์ํ ํจ์ํ(functional), ์ ์ ํ์ ์ง์ (statically typed) ์ธ์ด
- ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ฐ๊ตฌ์ ํ์ํ ๊ณตํต ์ธ์ด ์ญํ ์ ํ๊ธฐ ์ํด ์ข์ ์์ด๋์ด๋ฅผ ๋ชจ์์ ๋ง๋ ์ธ์ด
- ํ์ง๋ง ๊ฐ๋ ๋ง ๊ฐ๋ค์ฐ์ง ์๋ฌด๋ ํ์ค์ผ์ ์ง์ ์ฐ์ง๋ ์๋๋ค๊ณ ํ๋ค.
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ด๋?
- ์์ํจ์, ์ธ๋ถ ํ๊ฒฝ(side effect)์ ์ํด ์ถ๋ ฅ์ด ๋ฐ๋๋ ์ผ์ด ์์. ํจ์์ ์ถ๋ ฅ ๊ฐ์ ์ค๋ก์ง ์ ๋ ฅ ๊ฐ์๋ง ์ํฅ ๋ฐ์.
- ํจ์๊ฐ 1๊ธ ๊ฐ์ฒด(first class)๋ก ์ทจ๊ธ ๋ฐ์. ์ฝ๊ฒ ๋งํด ํจ์ ์์ฒด๋ฅผ ๋ณ์์ ์ ์ฅํ๊ฑฐ๋ ๋ฐํ/์ ๋ฌ ํ ์ ์์.
- ๋ช ๋ น์ ์คํํ๋ค๋ ๊ฐ๋ ๋ณด๋ค๋ ์(expresison)์ ์ ์ํ๊ณ ๊ทธ ์์ ๊ฐ์ (eval) ๊ตฌํ๋ ๊ฐ๋ ์ผ๋ก ์ฝ๋ ๊ตฌ์ฑ.
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์์
ํ์ฌ ํจ์ํ์ ๊ฐ์ฅ ์ ํ์ฉํ๊ณ ์๋ ๋ํ์ ์ธ ์ธ์ด๋ ์๋ฐ์คํฌ๋ฆฝํธ.
์๋ฐ์คํฌ๋ฆฝํธ ์์ ๋ฅผ ํตํด ๊ธฐ์กด์ ํ๋ก๊ทธ๋๋ฐ ๋ฐฉ์๊ณผ ํจ์ํ์ด ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ๋น๊ตํด๋ณด์.
์ผ๋ฐ์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋
// ์ ํต์ ์ธ ๋ช
๋ นํ(C์ธ์ด) ๋ฐฉ์์ผ๋ก, ๋ณ์๋ก ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๊ณ ์ฝ๋๋ฅผ ํ์ค์ฉ ์คํํ๋ค.
// names = [ ๋ฐ์ดํฐ1, ๋ฐ์ดํฐ2 ... ]
const result = [];
for (let i = 0; i < names.length; i += 1) {
const name = names[i];
const spaceName = name.replace(/(_|-)/, " ");
const splitName = spaceName.split(" ");
for (let j = 0; j < splitName.length; j += 1) {
let partName = splitName[j];
partName = partName.charAt(0).toUpperCase() + partName.slice(1);
splitName[j] = partName;
}
result.push(splitName.join(' '))
}
result.sort();
ํจ์ํ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋
// ํจ์๋ฅผ 1๊ธ ๊ฐ์ฒด(first-class citizen)๋ก ์ทจ๊ธํ๋ค. ์ฝ๊ฒ๋งํด ๋ณ์์ฒ๋ผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๊ณ ์ฃผ๊ณ ๋ฐ์ ์ ์๋ค.
// ๋ถ์ํจ๊ณผ(side-effect)๋ฅผ ์์ ๊ธฐ ์ํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฝ๋ ๊ฒ ์ด์ธ์ ์ง์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค.
// names = [ ๋ฐ์ดํฐ1, ๋ฐ์ดํฐ2 ... ]
const replaceSpace = (str) => {
return str.replace(/(_|-)/, ' ');
}
const startCase = (str) => {
return str.charAt(0).toUpperCase() + str.slice(1);
}
const changePartStartCase = (str) => {
return str.split(' ').map(startCase).join(' ')
}
names // names ๊ฐ์ฒด๋ฅผ ์ฝ์ด๋ค์ธ๋ค. ์ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์์ ํ์ง ์๋๋ค.
.map(name => replaceSpace(name)) // ๋ฏธ๋ฆฌ ์ ์ํด๋ ํจ์๋ฅผ ์ ์ฉ์ํจ๋ค.
.map(name => changePartStartCase(name))
.sort()
// map()์ ํด๋น ๊ฐ์ฒด๋ฅผ ์ฝ์ด๋ค์ฌ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
// ์ฆ ์ฌ๊ธฐ์์๋ sort()๋ names๋ฅผ ๊ฑด๋๋ฆฌ์ง ์๋๋ค.
์์ํจ์๋
ํ์ค์ผ ์์ ์์ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ์ ํญ์ ์ฐธ์กฐ ํฌ๋ช (referentially transparent)ํ๋ค.
๋ง์ด ์๋นํ ์ด๋ ค์ด๋ฐ, ์ด๋ฅผ ํ์ด์ ๋งํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
- ๊ฐ์ ์ํ ๋ณ๊ฒฝ(mutation)์ด ์๋ค. ๋ชจ๋ ๋ณ์, ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ ์ด๊ธฐํ ์ดํ ๋ถ๋ณ(immutable)ํ ๊ฐ์ด๋ค.
- ํจ์์ ์ํฅ์ ์ฃผ๋ ์ธ๋ถํ๊ฒฝ(side effect)์ด ์๋ค.
(๋ฉ๋ชจ๋ฆฌ ๊ฐ์ ์ง์ ์์ ํ์ง ์๋๋ค. ์ ์ญ๋ณ์๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ๋ฉ๋ชจ๋ฆฌ I/O๋ฑ์ ๋ฐ์ ์ํค์ง ์๋๋ค.) - ์ฆ, ๊ฐ์ ํจ์์ ๊ฐ์ ์ธ์๋ฅผ ์ ๋ฌํ๋ฉด ์ธ์ ๋ ๊ฐ์ ๊ฒฐ๊ณผ ๊ฐ์ ๋ณด์ฅ๋ฐ๋ ์์ํ ํจ์ ๊ทธ ์์ฒด์ด๋ค.
์ง์ฐ ๊ณ์ฐ ํ๊ฐ (Lazy Evaluation)
ํ๋ก๊ทธ๋จ์์ ์ฝ๋๊ฐ ์คํ ๋ ๋, ๊ฐ์ ํ๊ฐ(eval)ํ๋ ๋ฐฉ๋ฒ์๋ ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋ค.
ํ์ค์ผ์์๋ Lazyํ๊ฒ ํจ์๋ฅผ ํ๊ฐํ๋ค. ์ฝ๊ฒ ๋งํด ํจ์์ ๊ฐ์ด ์ค์ ๋ก ์ฌ์ฉํ๊ธฐ ์ ์ ๋ฏธ๋ฆฌ ๊ณ์ฐํ์ง ์๋๋ค.
์ ๊ณฑ ํจ์ square์ ์คํ์์ผ ๊ฐ์ ์ป๋ ๊ณผ์ ์ ์ดํด๋ณด์.
#strict - ์์ด ๋์ฌ ๋ ๋ง๋ค ๋ฐ๋ก ๊ฐ์ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ
square(3 + 4)
square(7)
7 * 7
49
#Lazy - ์ต๋ํ ๋ฆ์ถ๋ค๊ฐ ๋์ค์ ๊ณ์ฐํ๋ ๋ฐฉ๋ฒ
square(3 + 4)
(3 + 4) * (3 + 4)
7 * (3 + 4)
7 * 7
49
Lazyํ๊ฒ ๊ฐ์ ํ๊ฐํ๋ฉด
- ๊ณ์ฐํ ๋ ํ์ํ ์ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ณ
- ์ฌ๋ฌ ํจ์๋ฅผ ์ฝ๊ฒ ํฉ์น๊ณ ๋ ผ๋ฆฌ์ ์ผ๋ก ์์ ํํ(ex ๊ฐฏ์๊ฐ ๋ฌดํ์ธ ๋ฆฌ์คํธ ์ ๊ทผ) ํ ์ ์์ผ๋ฉฐ
- ํ๋ก๊ทธ๋จ์์ ํน์ ๊ธฐ๋ฅ์ ํ๋ ํจ์๋ฅผ ์ฝ๊ฒ ๋ถ๋ฆฌํ ์ ์๊ณ ์คํ ๋์ค ์ค๋ฅ์ ์ํ๋ฅผ ํ์ ํ ์ ์๋ค
ํ์ง๋ง ํ๋ก๊ทธ๋จ์ ์๊ฐ/๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ ํจํด์ ํ์ ํ๊ธฐ ์ด๋ ค์์ง๊ณ , ๋ฏธ๋ฃจ๊ณ ๋ฏธ๋ฃจ๋ค๊ฐ ๋ง์ง๋ง์ ๊ณ์ฐ ๊ณผ์ ์์ ๋ชจ๋ ์ฐ์ฐ์ ์ํํ๋ ๊ฒ์ด ์์คํ ์ ํฐ ๋ถ๋ด์ ์ค ์ ์๋ค๋ ๋จ์ ์ด ์๋ค.
'๐ฑBackend > Haskell' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
์์ฃผ ๋ฉ์ง ํ์ค์ผ์ ๊ฐ์ด ๋ฐฐ์๋ณด์ #3 (0) | 2021.04.20 |
---|---|
์์ฃผ ๋ฉ์ง ํ์ค์ผ์ ๊ฐ์ด ๋ฐฐ์๋ณด์ #2 (0) | 2021.04.17 |
Haskell์ ํ๋ก์ ํธ ๊ตฌ์กฐ(stack project) (0) | 2021.03.25 |
ํ์ค์ผ ๊ฐ๋ฐํ๊ฒฝ (stack + IntelliJ plugin) (0) | 2021.03.11 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev