Skip to content

Latest commit

ย 

History

History
163 lines (110 loc) ยท 6.23 KB

kleisli-composition๊ด€์ -Promise.md

File metadata and controls

163 lines (110 loc) ยท 6.23 KB

Kleisli Composition ๊ด€์ ์—์„œ์˜ Promise

ํ•จ์ˆ˜ํ˜• ๊ฐ•์˜ ์„น์…˜8 ๋‚ด์šฉ ์ •๋ฆฌ
(๊ฐ•์˜๋ช…: ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ JavaScript ES6+ ์œ ์ธ๋™ ๊ฐ•์‚ฌ๋‹˜)

Promise๋Š” Kleisli Composition์„ ์ง€์›ํ•˜๋Š” ๋„๊ตฌ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
Kleisli arrow ํ•จ์ˆ˜ ํ•ฉ์„ฑ๋ฐฉ๋ฒ•์€ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ์˜ ํ•จ์ˆ˜ ํ•ฉ์„ฑ์„ ์•ˆ์ „ํ•˜๊ฒŒ ํ•˜๋Š” ํ•˜๋‚˜์˜ ๊ทœ์น™์ด๋‹ค.
์ƒํƒœ, ํšจ๊ณผ, ์™ธ๋ถ€์„ธ์ƒ์— ์˜์กด์„ ์•ˆํ• ์ˆ˜๊ฐ€ ์—†๊ธฐ์— ํ•จ์ˆ˜ ํ•ฉ์„ฑ์ด ์›ํ•˜๋Š”๋Œ€๋กœ ๋˜์ง€์•Š์„ ์ˆ˜ ์žˆ๋‹ค.
์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜ํ•ฉ์„ฑ ๋ฐฉ๋ฒ•์ด๋‹ค.

// f . g // f์™€ g๋ฅผ ํ•จ์ˆ˜ ํ•ฉ์„ฑํ–ˆ๋‹ค๊ณ  ํ–ˆ์„๋–„
// ์–‘ ๋ณ€์— x๊ฐ€ ๊ฐ™๋‹ค๋ฉด ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™๋‹ค๋ผ๋Š” ๋ฒ•์น™
// f(g(x)) = f(g(x)) // x ์ธ์ž๊ฐ€ ์ „๋‹ฌ๋˜์—ˆ์„๋•Œ์˜ ๊ฒฐ๊ณผ๋Š” ์–ด๋Š์‹œ์ ์— ํ•˜๋”๋ผ๋„ ํ•ญ์ƒ ๋™์ผํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์‹์ด ์„ฑ๋ฆฝ๋˜์–ด์•ผํ•จ

ํ•˜์ง€๋งŒ ์‹ค๋ฌด์—์„œ๋Š” ์ขŒ๋ณ€ f(g(x))๋ฅผ ํ‰๊ฐ€ํ• ๋•Œ g๊ฐ€ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๋Š” ๊ฐ’์ด ์šฐ๋ณ€ f(g(x))๋ฅผ ํ‰๊ฐ€ํ• ๋•Œ๋Š” ๋‹ค๋ฅธ๊ฐ’์œผ๋กœ ๋ณ€ํ•ด์žˆ๋‹ค๊ฑฐ๋‚˜ ๊ฐ’์ด ์—†์–ด์ง€๊ฑฐ๋‚˜ ํ•˜๋Š” ์ƒํ™ฉ์œผ๋กœ ์ธํ•ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ณ  ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ๋Š” f(g(x)) = f(g(x))๊ฐ€ ์„ฑ๋ฆฝ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์‹ค์ƒ ์ˆœ์ˆ˜ํ•œ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ• ์ˆ˜๊ฐ€์—†๋‹ค.
โ€”> ๊ทธ๋Ÿฐ ์ƒํ™ฉ์—์„œ๋„ ํŠน์ •ํ•œ ๊ทœ์น™์„ ๋งŒ๋“ค์–ด ํ•ฉ์„ฑ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค๊ณ  ์ด๊ฒƒ์„ ์กฐ๊ธˆ๋” ์ˆ˜ํ•™์ ์ด๋ผ๊ณ  ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜ ํ•ฉ์„ฑ๋ฒ•์ด Kleisli Composition ์ด๋‹ค.

  • Kleisli Composition ๊ทœ์น™ - g์—์„œ ์—๋Ÿฌ๊ฐ€ ๋‚œ ๊ฒฝ์šฐ
`f(g(x))` ์ด๋ ‡๊ฒŒ ์‹คํ–‰ํ–ˆ์„๋•Œ `g(x)`x๋ฅผ g์— ์ „๋‹ฌํ–ˆ์„๋•Œ ์—๋Ÿฌ๊ฐ€๋ฐœ์ƒํ•˜๋ฉด f(g(x))์™€ g(x)์˜ ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™๋‹ค๊ณ  ๋ณผ์ˆ˜ ์žˆ๋‹ค.
// f(g(x)) = g(x) // ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“œ๋Š” ์‹์œผ๋กœ ํ•ฉ์„ฑ๋˜๋Š” ๊ฒƒ์„  Kleisli Composition๋ผ๊ณ  ํ•œ๋‹ค.

g์—์„œ ๋ฐ”๋ผ๋ณด๋Š” ๊ฐ’์ด ์ž˜๋ชป๋˜๊ฑฐ๋‚˜ x์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์›ํ•˜์ง€์•Š๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค๊ฒŒ ๋˜๋Š”๋ฐ
g(x)๊ฐ€ ๋ฆฌํ„ดํ•œ ๊ฐ’์ด f(g(x))์ฒ˜๋Ÿผ f๋ฅผ ํ•ฉ์„ฑํ•˜์ง€์•Š์•„๋„ ์–‘๋ณ€์ด ๋™์ผํ•œ ๊ฐ’์ด ๋งŒ๋“ค์–ด์ง€๋Š” ํ•ฉ์„ฑ์ด๋‹ค.

  • ์˜ˆ์‹œ
var users = [
	{ id: 1, name: 'aa' },
	{ id: 2, name: 'bb' },
	{ id: 3, name: 'cc' },
];

//์œ ์ €๋ฅผ id๊ฐ’์œผ๋กœ ์ฐพ๋Š” ํ•จ์ˆ˜
const getUserById = id => find(u => u.id == id, users);

// name์„ ์ถ”์ถœํ•˜๋Š” ํ•จ์ˆ˜
const f = ({name}) => name;
const g = getUserById;

// g๋ฅผ ํ†ตํ•ด ์ƒํƒœ๋ฅผ ์ฐพ๊ณ  ์ฐพ์€ ๊ฒฐ๊ณผ์— f๋ฅผ ์—ฐ์†์ ์œผ๋กœ ์‹คํ–‰ํ•ด์„œ ๊ทธ์‚ฌ๋žŒ์˜ ์ด๋ฆ„์„ ์ถ”์ถœํ•˜๋Š” ํ•ฉ์„ฑ์„ ํ•˜๊ณ ์žํ•œ๋‹ค๋ฉด 
// ํ•จ์ˆ˜ํ•ฉ์„ฑ์ด ๋œ fg๋Š” ์•„๋ž˜์™€๊ฐ™์ด ๋งŒ๋“ค์ˆ˜ ์žˆ๋‹ค.
const fg = id => f(g(id))

fg(2);// g์—์„œ { id: 2, name: 'bb' },์ด ๊ฐ์ฒด๋ฅผ ์ฐพ์•„๋‚ด๊ณ  ๊ทธ๋‹ค์Œ์— f์—์„œ name์„ ๊ตฌ์กฐ๋ถ„ํ•ดํ•˜์—ฌ ๊บผ๋‚ด name์„ ์ „๋‹ฌํ•˜๊ฒŒ๋จ

// 2๋ผ๋Š” ๊ฐ’์ด ์ž˜ ์ „๋‹ฌ๋œ๋‹ค๋ฉด ๋ฌธ์ œ์—†์ด ๋™์ž‘ํ• ๊ฒƒ
log(fg(2));

// ํ•ญ์ƒ ๋™์ผํ•œ ๊ฐ’์„ ์ž˜๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ
log(fg(2) == fg(2));
  • ์‹ค๋ฌด์—์„œ์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ
// ์‹ค๋ฌด์—์„œ๋Š” users์˜ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜๊ธฐ๋„ํ•œ๋‹ค.

// ์˜ˆ๋ฅผ๋“ค์–ด ์•„๋ž˜์ฒ˜๋Ÿผ 2๋ฒˆ์˜ pop์ด ๋ฐœ์ƒํ•ด์„œ user์˜ ์ƒํƒœ๋ฅผ ๋ณธ๋‹ค๋ฉด
//users.pop();
//users.pop();
//log(users); // [{id:1, name: 'aa'}] ์ด๋Ÿฐ์‹์œผ๋กœ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•ด์žˆ๊ณ  2๋ฒˆ์˜ ์œ ์ €๊ฐ€ ์‚ฌ๋ผ์ ธ์žˆ์Œ

// ์ •์ƒ ์ƒํ™ฉ
const result = fg(2);

users.pop();
users.pop();

// ์—๋Ÿฌ ๋ฐœ์ƒ
const result2 = fg(2); 

const getUserById = id => find(u => u.id == id, users);
const f = ({name}) => name;
const g = getUserById;
์œ„ ์ฝ”๋“œ ์ž์ฒด๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ์ฝ”๋“œ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ํ•จ์ˆ˜๋“ค์ด์ง€๋งŒ ํ•จ์ˆ˜ ๋‘๊ฐœ(f์™€ g)๋ฅผ ํ•ฉ์„ฑํ•œ ์ƒํ™ฉ์—์„œ

const fg = id => f(g(id)) ์œ„ํ—˜ํ•œ ์ƒํ™ฉ์ด ์ƒ๊ธฐ๊ฒŒ๋œ๋‹ค.

  • ์™œ ์œ„ํ—˜ํ•œ ์ƒํ™ฉ์ด ์ƒ๊ธฐ๋Š”๊ฐ€?
  1. f๋ผ๋Š” ํ•จ์ˆ˜๋Š” ํ•ญ์ƒ ๋ฐ˜๋“œ์‹œ name์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•˜์„ ๋•Œ๋งŒ ์ •์ƒ๋™์ž‘ํ•˜๊ณ ์š”

  2. g๋ผ๋Š” ํ•จ์ˆ˜๋Š” users์•ˆ์— ๊ฒฐ๊ณผ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„๋•Œ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€๋ฉ๋‹ˆ๋‹ค

๋งŒ์•ฝ pop์ด ์ผ์–ด๋‚˜์ง€์•Š์•˜๊ณ  fg์— users์— ์กด์žฌํ•˜๋Š” id๋งŒ ์ „๋‹ฌ๋œ๋‹ค๋ฉด ๋ฌธ์ œ์—†์ด ๋™์ž‘๋˜๋Š”๋ฐ pop๊ณผ๊ฐ™์€ ์™ธ๋ถ€์˜ ๋ณ€ํ™”๊ฐ€ ์ผ์–ด๋‚œ๋‹ค๋ฉด ์ƒํ™ฉ์— ๋”ฐ๋ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•จ์ˆ˜๋ฅผ ํ•ฉ์„ฑํ•˜๋ฉด์„œ ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€ ์•Š๊ฒŒ ํ•˜๋Š”๊ฒƒ์ด Kleisli arrow๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

Kleisli arrow๋กœ ํ•ฉ์„ฑํ•ด๋ณด๊ธฐ

const fg = id => Promise.resolve(id).then(g).then(f);

fg(2).then(log); // fg(2) ์‹คํ–‰๊ฒฐ๊ณผ๋ฅผ log๋กœ ์ถœ๋ ฅํ•ด๋ณด๊ธฐ // bb
  • ์™ธ๋ถ€์„ธ์ƒ ๋ณ€ํ™” ์ค˜๋ณด๊ธฐ
users.pop();
users.pop();

fg(2).then(log);// ์—๋Ÿฌ๋ฐœ์ƒ
  • ์—๋Ÿฌ๋ฐœ์ƒ๋˜๋Š” ์ƒํ™ฉ์—์„œ Promise๋Š” ํ•จ์ˆ˜ ํ•ฉ์„ฑ์„ ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
// ๊ฒฐ๊ณผ๊ฐ€ ์—†์„๋•Œ Promise.reject์ด๋ผ๋Š” ๊ฐ’์„ ๋ฆฌํ„ดํ•˜๊ฒŒ ํ•œ๋‹ค.
const getUserById = id => find(u => u.id == id, users) || Promise.reject('์—†์Œ!');

users.pop();
users.pop();

g(1) // ์ •์ƒ
g(2) // rejected๋œ ํ”„๋กœ๋ฏธ์Šค ๊ฐ’์„ ๋ฐ›๊ณ ์žˆ์Œ
  • ๊ฒฐ๊ตญ gํ•จ์ˆ˜๋Š”

g(2)๋Š” ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋Š” ๋˜‘๊ฐ™์€ g(2)๋ฅผ ํ˜ธ์ถœํ•ด๋„ ์—‰๋šฑํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋œ ์ƒํ™ฉ
์ด๋ ‡๊ฒŒ ์ฝ”๋”ฉํ•ด๋†“๊ณ  ๋‚˜์„œ fg(2).then(log); ๋˜‘๊ฐ™์ด ์‹คํ–‰ํ•˜๋ฉด ์•„๊นŒ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ rejected๋œ ํ”„๋กœ๋ฏธ์Šค๊ฐ€ ์ถœ๋ ฅ๋˜๊ฒŒ๋œ๋‹ค.

  • ๋งˆ์น˜ ํ•จ์ˆ˜ ํ•ฉ์„ฑ์ด g๋งŒ ์ผ์–ด๋‚œ๊ฒƒ์ฒ˜๋Ÿผ

fg(2).then(log); ์‹คํ–‰๊ฒฐ๊ณผ๋Š” Promise๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฆฌํ„ดํ•˜๊ณ  ํ•จ์ˆ˜ํ•ฉ์„ฑ์ด ๋งˆ์น˜ g๋งŒ ์‹คํ–‰ํ•œ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ƒํ™ฉ์œผ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

  • ๋น„๊ต
f(g(2)); // undefined๋ผ๋Š” ์—‰๋šฑํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ด // ํ”„๋กœ๋ฏธ์Šค์— name์„ ์ฐพ์œผ๋‹ˆ undefined

fg(2).then(log);// ์—‰๋šฑํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„๋“ค์ด์ง€์•Š๊ณ  log๋„ ์ถœ๋ ฅ๋˜์ง€์•Š๋Š”๋‹ค.
  • catch๋กœ ์•ˆ์ „ํ•˜๊ฒŒ!
const fg = id => Promise.resolve(id).then(g).then(f).catch(a => a); // reject๋˜๋ฉด catch๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๊ฐ

fg(2).then(log);

g(2)๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์—†๋‹ค๋ผ๋Š” ๊ฐ’์ด ๋‚˜์˜ค๊ฒŒ ๋˜๊ณ 
ํ•ฉ์„ฑ๋œ ํ•จ์ˆ˜ fg(2).then(log);๋ฅผ ์‹คํ–‰ํ•˜๊ฒŒ๋˜๋ฉด โ€œ์—†์–ด์š”!โ€๊ฐ€ ๋–จ์–ด์ง€๊ฒŒ๋œ๋‹ค.
ํ•จ์ˆ˜ ํ•ฉ์„ฑ ๊ณผ์ •์—์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด(ex. g์—์„œ ์—๋Ÿฌ๋ฐœ์ƒ) ๋‹ค์Œ๊ณผ์ •์„ ์‹คํ–‰์•ˆํ•˜๊ณ (ex. f์‹คํ–‰์•ˆํ•จ) catch๊ฐ€ ์‹คํ–‰๋˜๊ณ  ๊ทธ๋‹ค์Œ .then(log)๋กœ ํ˜๋Ÿฌ๊ฐˆ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

Promise๋ฅผ ํ†ตํ•ด Kleisli ๊ด€์ ์„ ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • Kleisli ๊ด€์ 
// f(g(x)) = f(g(x))
// f(g(x)) = g(x)