Monoid

2022. 9. 22. 00:00CSharp/Functional Programming

반응형

https://en.wikipedia.org/wiki/Magma_(algebra)
https://blog.ploeh.dk/2017/10/05/monoids-semigroups-and-friends/

 

 

https://blog.ploeh.dk/2017/10/06/monoids/

 

Monoids

Introduction to monoids for object-oriented programmers. This article is part of a larger series about monoids, semigroups, and related concepts. In this article, you'll learn what a monoid is, and what distinguishes it from a semigroup. Monoids form a sub

blog.ploeh.dk

 

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);

자그렇다면 이것을 사용하는 이점은 무엇일까

연산의 순서가 값에 영향을 주지 않는다는 이야기는 병렬처리를 하여도 최종연산의 값이 같다는 이야기다.

 

관련영상

https://youtu.be/x16xy5pZ25k

 

 

반응형

'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