> 추상대수학에서, 모노이드는 항등원을 갖는, 결합 법칙을 따르는 이항 연산을 갖춘 대수 구조이다. 군의 정의에서 역원의 존재를 생략하거나, 반군의 정의에서 항등원의 존재를 추가하여 얻는다. - 위키피디아
## Set
- 집합
#### Magma
- Set에 이항 연산자가 추가된 타입
```ts
interface Magma<T> {
readonly op: (first: T, second: T) => T
}
```
## Semigroup
- 반군
- Magma가 결합 법칙을 만족하면 Semigroup이 된다.
```ts
// 결합 법칙을 타입으로 표현할 수 있는 방법이 있을까...?
interface Semigroup<T> extends Magma<T> {}
// 뺄셈은 결합 법칙을 만족하지 않으므로 아래는 Semigroup이 아니다.
const notSemigroup: Magma<number> = {
op: (first, second) => first - second;
};
// 덧셈은 결합 법칙을 만족하므로 아래는 Semigroup이다.
const semigroup: Magma<number> = {
op: (first, second) => first + second;
};
```
### folding
- 여러 개의 Monoid를 연결하는 방법
- Semigroup이 아닐 경우, 즉 결합 법칙을 만족하지 않는 경우에는 folding의 결과가 달라질 수 있기 때문에 folding이 불가능하다.
- folding을 할 수 있으면 여러 연산을 병렬적으로 처리할 수 있다.
```ts
notSemigroup.op(notSemigroup.op(1, 2), 3) // => -4
notSemigroup.op(1, notSemigroup.op(2, 3)) // => 0
semigroup.op(semigroup.op(1, 2), 3) // => 6, foldLeft
semigroup.op(1, semigroup.op(2, 3)) // => 6, foldRight
// 병렬은 이렇게...
const firstResult = semigroup.op(1, 2);
const secondResult = semigroup.op(3, 4);
const finalResult = semigroup.op(firstResult, secondResult);
```
## Monoid
- 모노이드
- Semigroup이 항등원을 가지면 Monoid가 된다.
```ts
interface Monoid<T> extends Semigroup<T> {
zero: T;
}
const sumNumberMonoid: Monoid<number> = {
op: (first, second) => first + second;
zero: 0;
};
const multipleNumberMonoid: Monoid<number> = {
op: (first, second) => first * second;
zero: 1;
};
const addStringMonoid: Monoid<string> = {
op: (first, second) => first + second;
zero: '';
};
```
#monoid #functional_programming