참고
타입
타입은 집합이다.
string, int, float, double 등. 원시타입(Primitive type) 이외에도 enum, struct, class 등을 사용하여 우리가 원하는 타입을 추상화를 통해 만들 수 있다.
Boolean = (False, True }
Int = { ... -2, -1, 0, 1, 2 }
String = { "", "a", "b", "aa" ... }
함수
함수는 두 집합을 연결하여 관계를 만들어 주는 연산이다.
함수 f는 x와 y를 연결하여 관계를 만들어 주는 함수
f: x -> y
합성
함수를 확장할 수 있도록 한다.
함수를 합성 할 수 있어야 큰 연산을 작은 단위로 쪼개어 해결하고, 그 결과들을 모아 문제를 해결할 수 있다.
f: x -> y
g: y -> z
fg: x -> z
순수함수
동일한 인자가 주어졌을 때 항상 동일한 결과를 반환하고 외부의 상태를 변경하지 않는 함수
함수가 외부상태를 읽어 사용하여 자신이 만드는 결과에 영향을 준다면 외부 상태에 의존하고 있는 것으로 순수함수가 아니다.
사이드 이펙트
어떤 함수가 존재할 때, 이 함수가 순수함수가 될 수 없게 만드는 모든 것
객체지향 언어에서 발생하는 사이드 이펙트
멤버 함수는 this 포인터를 통해 멤버 변수를 사용하는 경우가 많음 이 경우 this 포인터를 사용하는 것 자체가 외부환경에 의존하는 것 calc 함수에 동일한 인자가 주어졌을 때 동일한 결과값을 반환하는 것은 factor 멤버 변수가 어떻게 관리되는냐에 달려 있다.
class SomeClass {
factor: number = 1;
calc(value: number): number {
return value * this.factor;
}
}
factor를 외부에서 접근할 수 없게 하고 상수로 정의하여 값이 수정될 가능성을 제거
class SomeClass {
private factor: number = 1;
calc(value: number): number {
return value * this.factor;
}
}
만약 calc 함수에 다른 factor를 적용해야 하면 factor를 인자로 받는 것이 좋다.
class SomeClass {
calc(value: number, factor: number): number {
return value * factor;
}
}
순수함수와 사이드 이펙트
만약 FileName을 받아 File을 반환하는 함수가 있다면 파일의 유무(외부 상태)에 따라 반환하는 결과값이 다를 것이다. 독립된 함수일 때 결과값 집합 이외의 집합값을 반환할 때 사이드 이펙트가 있다고 할 수 있다.
그렇다면 결과값 집합과 오류값 집합을 하나의 집합으로 만들면? 모나드는 함수 내부에서 발생할 수 있는 사이드 이펙트를 결과 집합에 함께 포함하는 타입 함수 실행 결과를 항상 모나드로 반환하여 순수함수 성질을 잃지 않게 하는 것 함수의 결과값에 모나드를 적용하면 내부에서 어떤 사이드 이펙트가 발생하던 그 함수 자체는 순수함수로 만들 수 있다.
구체타입 = 원시타입(boolean, int, string, float, double) + 커스텀 타입(class, struct)
이 구체타입을 한 번 더 추상화 한 것이 모나드 모나드는 함수에 들어가고 반환되는 값을 한 차례 추상화한 것.
f : FileName -> Monad[File, Error]
흐름
모나드를 통해 함수를 합성하기 위해서는 함수의 인자와 결과값이 모두 모나드로 되어 있어야 한다.
f : Monad -> Monad
g : Monad -> Monad
h : Monad -> Monad
h ○ g ○ f : Monad -> Monad
모나드 개념 요약
- 구체타입을 추상화한 타입
- 추상화 속엔 사이드이펙트도 포함할 수 있다.
- 사이드이펙트가 있는 함수를 순수함수로 바꾸어 주는 것
- map과 flatMap을 통한 함수 합성으로 데이터가 계속 흐를 수 있게 해 주는 것.
- 따라서 Monad는 Side Effect를 내포하면서 map과 flatmap을 정의한 타입
- 모나드는 문맥을 담는다.