2022. 9. 22. 00:00ㆍCSharp/Functional Programming
https://blog.ploeh.dk/2017/10/06/monoids/
Monoids 는 Semigroups 의 하위 집합이다. Monoids를 관리하는 규칙은 Semigroups에 대한 규칙보다 더 엄격하다.
Monoids 는 데이터 유형과 연산의 조합이다. 유형 자체가 아니라 작동하는 함수(method) 다.
1+2 와 6*7 의 공통점은 무엇일까?
- 연관 (Associative)
- 이진 연산 (Binary Operations)
- 중립요소 (Neutral Element) == Identity
이진 연산(Binary Operations)
아래와 같은 C# 메서드는 적절한 이진 연산이다.
public Student BinaryOp(Student x, Student y) => y;
public Student AnotherBinaryOp(Student x) => x;
하지만 아래와 같은 경우는 아니다.
public Doctor NotBinaryOp(Student x, Teacher y) => new Doctor();
즉 이진 연산(Binary Operations)은 두 입력 값이 동일한 유형이고 반환 유형이 입력 유형과 동일하다는 것이다.
연관 (Associative)
연관은 연산의 순서가 중요하지 않다는 것을 의미한다.
(2 + 3) + 4 = 2 + (3 + 4) = 2 + 3 + 4 = 9
(2 * 3) * 4 = 2 * (3 * 4) = 2 * 3 * 4 = 24
위 덧셈과 곱셈은 괄호의 위치가 달라 계산의 우선순위가 바뀐다.
하지만 이런경우에도 결과 값은 똑같다.
이런 경우를 연관 이라고 한다.
C# 에서 다음과 같은 코드로 구현해 볼수 있다.
public record class Number(int X)
{
public Number Add(Number number) => number with { X = X + number.X };
public Number Mul(Number number) => number with { X = X * number.X };
}
var number1 = new Number(1);
var number2 = new Number(2);
var number3 = new Number(3);
var addEqual = number1.Add(number2).Add(number3) == number1.Add(number2.Add(number3));
Console.WriteLine(addEqual);
var mulEqual = number1.Mul(number2).Mul(number3) == number1.Mul(number2.Mul(number3));
Console.WriteLine(mulEqual);
중립요소 (Neutral Element) == Identity
중립요소 Identity 란 아무것도 하지 않는 값이다.
예를 들어 값에 0을 추가해도 값이 변경되지 않기 때문에 0이다.
0 + 42 = 42 + 0 = 42
위의 연산의 Identity 를 method 로 표현한다면 다음과 같을 것이다.
public int Identity() => 0;
자 이제 정리 해보자
Monoid 는 Semigroup 의 규칙과 Identity 규칙을 유지 하는 요소 집합이다.
Identity: a ∈ S, a·e = e·a = a ∈ S
자 이제 Monoid 의 간단한 예제를 구현해 보자
public record class Number(int X)
{
public Number Add(Number number) => number with { X = X + number.X };
public Number Mul(Number number) => number with { X = X * number.X };
public Number AddIdentity => new Number(0);
public Number MulIdentity => new Number(1);
}
var number1 = new Number(1);
var number2 = new Number(2);
var addEqual = number1.AddIdentity.Add(number2) == number2.Add(number1.AddIdentity);
Console.WriteLine(addEqual);
var mulEqual = number1.MulIdentity.Mul(number2) == number2.Mul(number1.MulIdentity);
Console.WriteLine(mulEqual);
자그렇다면 이것을 사용하는 이점은 무엇일까
연산의 순서가 값에 영향을 주지 않는다는 이야기는 병렬처리를 하여도 최종연산의 값이 같다는 이야기다.
관련영상
'CSharp > Functional Programming' 카테고리의 다른 글
Quasigroups (유사군) (0) | 2022.09.23 |
---|---|
Semigroup (2) | 2022.09.21 |
Magma (2) | 2022.09.20 |
순수 함수 (Pure Function) (0) | 2022.09.19 |
Expression, Method chaining with Extension methods (0) | 2022.09.16 |