참고
모나드 정의
어떤 타입 M에 대해 아래의 두 함수, pure과 compose가 존재할 때, M은 모나드이다.
type Pure = <A>(a: A) => M<A>;
type Compose = <A, B, C>(f: (a: A) => M<B>, g: (a: B) => M<C>) => (a: A) => M<C>;
type M은 연산 M을 의미하며 type M\<A>는 A 타입의 연산 M을 의미 M\<number>는 number 타입의 값을 만드는 연산 M을 의미
pure 함수는 일반적인 값을 연산 M이 적용된 값인 것 처럼 꾸며 주는 함수
compose 함수는 같은 연산을 하는 두 프로그램을 받아 하나로 합치는 형태 모나드인 연산의 합성 가능성을 보장하는 함수로 합성 가능한 연산들만이 모나드가 될 수 있게 하기 위해 존재하는 제한
모나드 사용 이유
프로그래밍에서 모나드는 합칠 수 있는 연산을 정의하고 추상화 하기 위해 사용한다.
프로그램은 수 많은 서브 프로그램의 집합. 각각의 서브 프로그램들은 하나 하나가 연산이고 이들이 합쳐져 프로그램이 된다. 즉 프로그램은 연산의 집합이다.
정리하면 프로그램은 곧 연산이고, 연산은 곧 프로그램이다. 어떤 연산이 모나드로 정의되면 그 연산에 해당하는 모든 프로그램은 합쳐질 수 있다.
예시
Maybe
가장 간단한 형식의 모나드
type Maybe<A> = A | null;
const pure = <A>(value: A): Maybe<A> => {
return value;
};
const compose =<A, B, C>
(
f: (a: A) => Maybe<B>,
g: (a: B) => Maybe<C>
) =>
(a: A): Maybe<C> => {
const ma = f(a);
if (ma === null) return null;
else return g(ma);
};
pure<string>("10");
// -> 10
const makeNumber = (str: string): number | null => {
if (str.length === 0) return null;
else return Number(str);
};
const makeBoolean = (num: number): boolean | null => {
if (num === 0) return null;
else return Boolean(num);
}
compose<string, number, boolean>(makeNumber, makeBoolean)('10');
// -> true
compose<string, number, boolean>(makeNumber, makeBoolean)('');
// -> null
compose<string, number, boolean>(makeNumber, makeBoolean)('0');
// -> null