모나드란?
- 함수 합성 관점에서 Promise는 비동기 상황에서 함수 합성을 안전하게 하게 하는 도구
함수 합성이란
f(g(x))
이런 식으로 하나의 인자에 여러 함수가 실행되는 것
- 안전하게 함수를 합성하게 하는 것이 모나드고, 비동기적 상황에서는 Promise
모나드 예시
const g = a => a+1
const f = a => a*a
g(f(1)) // 4
g(f()) // 만약에 빈 값이 들어가면 에러가 남. 즉, 안전하게 합성된 것이 아님.
[] // 모나드는 박스라는 개념. 이 박스 안의 요소를 다루는 것
[1].map(g).map(f).forEach(a=> console.log(a)) // 4, 모나드는 map을 통해 함수를 합성한다.
[].map(g).map(f).forEach(a=> console.log(a)) // 값이 들어오지 않아도 에러가 나지 않는다.
Promise 예시
Promise.resolve(1).then(g).then(f).thne(res => console.log(res)) // 4
Promise.resolve().then(g).then(f).thne(res => console.log(res)) // NaN
- 여기서 Promise는 인자의 유무에 따른 함수 합성의 안전성을 보장하려는 것이 아닌, 비동기 상황을 고려하는 것.
Promise.resolve(()=> setTimeout()=> resolve(1), 100).then(g).then(f).thne(res => console.log(res)) // 4
- 즉, 특정 상황에서 안전한 합성하는 것을 통틀어 모나드한다.
Kleisli Composition란
Promise와 Kleisli Composition
- Promise는 Kleisli Composition를 지원하는 도구라고 할 수 있다.
- 오류가 있을 수 있는 상황에서 함수 합성의 규칙이다.
- 실무에서는 상태 변화나 외부 요인이 다양해서 항상 안정성을 보장받을 수 없다
예시
f(g(x)) = f(g(x)) // 실무에서는 왼쪽을 평가할 때와 오른쪽을 평가할 때 x가 달라질 수 있다.
- 위와 같은 상황에서 규칙을 만들어서 안전하게 합성하는 것이 Kleisli Composition
// 아래는 데이터
const users = [
{id:1, name:"a"},
{id:2, name:"b"},
{id:3, name:"c"}
]
// 아이디를 찾는 함수 (find는 curry적용)
const getIdByUser = (id) => find(u => u.id===id, user)
// name만 return하는 함수
const f = ({name}) => name
const g = getIdByUser
const fg = id => f(g(id))
fg(2) // a
// 만약 users의 상태가 변화했다 가정
user.pop()
user.pop()
fg(2) // 에러
- 외부 요인에 상관없이 안전한 합성을 하기 위해 코드 수정
const getIdByUser = (id) => find(u => u.id===id, user) || Promise.reject("error") // Promise 객체를 리턴하게 한다.
const fg = id => Promise.resolve(id).then(g).then(f)
// users 상태 변화
user.pop()
user.pop()
fg(2).then((res)=>console.log(res)) // reject에러,
- 여기서 중요한 점은 의도하지 않은 결과(undefined, NaN..)이 아닌 Promise 객체가 반환된다는 것.