Monad가 Monoid인 이유 수학 없이 이해하기
Tags: 모나드, monad, 모노이드, monoid
Published: 2020-03-25 04:54:33

---
title: Monad가 Monoid인 이유 수학 없이 이해하기
published: true
description: 모나드는 사실 모노이드일뿐
tags: 모나드,monad,모노이드,monoid
---

## Motivation

저는 처음 모나드/모노이드를 배울때 누군가가 “모나드는 모노이드일 뿐이야” 라고 설명해줬으면 얼마나 좋았을까 생각해요. 그걸 알았다면 두개를 따로 따로 배우느라 시간낭비 하지 않았을텐데 하는 아쉬움이있어요. 생각해보니 대부분의 프로그래머를 위한 Monad 와 Monoid 학습 자료들을 보면 Monad의 경우 업계에서 Monad란 무엇인가?! 라는 주제의 글을 금지하고 있을정도로 깊이있는 탐구보단 프로그래머관점에서의 표면적인 이해를 위한 자료가 많아요. Monoid 도 마찬가지죠. 물론 프로그래머로써 이 둘을 깊게 이해할 필요는 없어요. 그 때문인지 이 둘이 독립적으로 다뤄질 때가 많아요.

이 글에서는 최대한 프로그래머 관점에서 쉽게 모나드를 모노이드로 설명하고, 모노이드로 정의를 내려봄으로써 독자가 이 두 토픽을 확실하게 이해할 수 있게끔 노력해볼거에요.

들어가기 앞서 둘이 같다는걸 이해하는것은 전혀 어렵지 않고 손뻗으면 닿는, 바로 눈앞에있다는것을 먼저 보여드릴게요

우선 모나드와 모노이드의 문서상 정의부터 비교해보죠. 

{% katex %}
\begin{aligned}
&\text{Monad} \\\\
&\mu :: T^2 \rightarrow T \\\\
&\eta :: I \rightarrow T \\\\
&\mu(T,\mu(T^2)) = \mu(\mu(T^2),T) \\\\
&\mu(\eta(I),T) = \mu(T,\eta(I)) = T \\\\
\end{aligned}

\hspace{1em}

\begin{aligned}
&\text{Monoid} \\\\
&\otimes :: T \times T \rightarrow T \\\\
&i \\\\
&t_1 \otimes (t_2 \otimes t_3) = (t_1 \otimes t_2) \otimes t_3 \\\\
&i \otimes t = t \otimes i = t \\\\
\end{aligned}
{% endkatex %}

각 수식의 정확한 의미는 몰라도 굉장히 비슷한게 보이시나요?

각도를 다르게 해서 봐보죠.

{% katex %}
\text{Monad} \\\\
\text{}\\\\
\begin{gathered}
1 \\\\
\darr_{\eta} \\\\
T \\\\
\end{gathered}

\hspace{1em}

\begin{gathered}
T^2 \\\\
\darr_{\mu} \\\\
T \\\\
\end{gathered}

\hspace{1em}

\begin{gathered}
T \times 1  \\\\
\darr  \\\\
T  \\\\
\end{gathered}

\begin{gathered}
\xrightarrow{id\times\eta} \\\\
\\\\
\rightarrow \\\\
\end{gathered}

\begin{gathered}
T^2  \\\\
\darr_{\mu}  \\\\
T  \\\\
\end{gathered}

\begin{gathered}
\xleftarrow{\eta\times id}  \\\\
\\\\
\leftarrow  \\\\
\end{gathered}

\begin{gathered}
1 \times T  \\\\
\darr  \\\\
T  \\\\
\end{gathered}

\hspace{1em}

\begin{gathered}
T^3  \\\\
\darr_{id \times \mu}  \\\\
T^2  \\\\
\end{gathered}

\begin{gathered}
\xrightarrow{\mu\times id} \\\\
\\\\
\xrightarrow{\mu}  \\\\
\end{gathered}

\begin{gathered}
T^2  \\\\
\darr_{\mu}  \\\\
T  \\\\
\end{gathered}
{% endkatex %}

{% katex %}
\text{Monoid} \\\\
\text{}\\\\
\begin{gathered}
1 \\\\
\darr_{id} \\\\
T \\\\
\end{gathered}

\hspace{1em}

\begin{gathered}
T\times T \\\\
\darr_{\otimes} \\\\
T \\\\
\end{gathered}

\hspace{1em}

\begin{gathered}
T \times 1 \\\\
\darr  \\\\
T  \\\\
\end{gathered}

\begin{gathered}
\xrightarrow{1\times id} \\\\
\\\\
\rightarrow \\\\
\end{gathered}

\begin{gathered}
T \times T  \\\\
\darr_{\otimes}  \\\\
T  \\\\
\end{gathered}

\begin{gathered}
\xleftarrow{id \times 1}  \\\\
\\\\
\leftarrow  \\\\
\end{gathered}

\begin{gathered}
1 \times T  \\\\
\darr  \\\\
T  \\\\
\end{gathered}

\hspace{1em}

\begin{gathered}
T\times T\times T  \\\\
\darr_{1 \times \otimes}  \\\\
T\times T  \\\\
\end{gathered}

\begin{gathered}
\xrightarrow{\otimes\times 1} \\\\
\\\\
\xrightarrow{\otimes}  \\\\
\end{gathered}

\begin{gathered}
T\times T  \\\\
\darr_{\otimes}  \\\\
T  \\\\
\end{gathered}
{% endkatex %}

모양이 비슷하죠? 자세하게는 몰라도 둘이 같은걸 뜻한다는 느낌을 받을거에요.
모나드의 각 property들이 모노이드에 어떻게 대응하는지만 이해한다면 둘이 같은걸로 보이게 될거에요.

## Monad <-> Monoid

프로그래머한테 모나드 T의 정의는 다음과같은 signature를 가진 두 함수의 존재에요.

{% katex %}
\mu(T^2) \rightarrow T \newline
\eta(I) \rightarrow T
{% endkatex %}

프로그래머한테는 보통 {% katex inline %}\mu{% endkatex %} 는 `join`으로, {% katex inline %}\eta{% endkatex %}는 `return`으로 많이 알려져 있죠. {% katex inline %}T{% endkatex %}는 모나드 타입이고 {% katex inline %}T^2{% endkatex %}는 모나드 타입 {% katex inline %}T{% endkatex %} 를 두번 적용 한 거에요. 모나드 `List`가 {% katex inline %}T{% endkatex %}라면 `List`의 `List`가 {% katex inline %}T^2{% endkatex %}가 되겠죠.

물론 signature가 똑같다고 아무 함수나 되는건 아니에요. 만족해야하는 조건이 있어요. 하지만 이 조건을 컴파일러 레벨에서 강제할 수 있는 언어가 (제가알기론)없다보니 이름하야 monadic law는 프로그래머들에겐 무시당할 때가 많죠. 하지만 모나드가 모노이드라는 사실을 이해하기위해선 Monadic law 도 이해해야해요. 왜냐하면 Monadic Law는 두가지 (join의 룰, return의 룰)이 있는데 이 각각이 모노이드의 Associativity 와 Identity 에 대응이 되기 때문이에요.

### 모나드의 Join <-> 모노이드의 Associativity

{% katex inline %}\mu{% endkatex %} (혹은 join) 이 지켜야 하는 룰은 다음과 같아요

{% katex %}
\mu(T,\mu(T^2)) = \mu(\mu(T^2),T)
{% endkatex %}

모나드 타입 ({% katex inline %}T^3{% endkatex %})를 T로 두번 {% katex inline %}\mu{% endkatex %}한다고 할때 {% katex inline %}\mu(T^2, T){% endkatex %}를 먼저 하든 {% katex inline %}\mu(T,T^2){% endkatex %}를 먼저 하든 결과는 똑같아야 한다는 뜻이에요. 다시 `List`로 예를 든다면 `List<List<List>>.join().join()`의 결과와 `List<List<List>>.map(join).join()`의 결과는 언제나 같아야 한다는 뜻이에요.

이 룰이 다음과같은 Monoid의 Associativity 에 대응해요.

{% katex %}
(t_1 \otimes t_2) \otimes t_3 = t_1 \otimes (t_2 \otimes t_3)
{% endkatex %}

그림으로 표현해보면 더 와닿을거에요

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/in8dzhqgobk9g9mvsdsq.jpeg)

Monad의 {% katex inline %}\mu{% endkatex %}가 operator역할로 Monoid로써 Associativity 를 만족시켜줘요.

모나드의 세 T는 줄서서 하나의 타입으로 evaluate되길 기다리고 있어요. 양쪽 어느 쌍이 먼저 evaluate 되든 상관없어요 왜냐하면 monadic law 에 의해 결과는 똑같을것이기 때문이죠. 이 모나드의 property 는 모노이드의 associativity 와 대응돼요. 모노이드의 세 T는 줄서서 다른 algebraic value 로 evaluate 되길 기다리고있죠. 모노이드 역시 양쪽 어느 쌍이 먼저 evaluate 되든 상관없어요. 모노이드기 때문이죠.

### 모나드의 Return <-> 모노이드의 Identity

{% katex inline %}\eta{% endkatex %} (혹은 return) 가 지켜야 하는 룰은 다음과 같아요

{% katex %}
\mu(\eta(I),T) = \mu(T,\eta(I))
{% endkatex %}

{% katex inline %}\eta{% endkatex %}로 만든 T의 T든, T의 {% katex inline %}\eta{% endkatex %}로 만든 T든 {% katex inline %}\mu{% endkatex %}를 적용했을 때의 결과값은 똑같아야 한다는 뜻이에요. 다시 `List`로 예를들면 `List.map(return).join()`의 결과와 `return(List).join()`의 결과는 같아야 한다는 뜻이에요.

이 룰은 Monoid의 Identity 에 대응해요

{% katex %}
i \otimes t = t \otimes i = t
{% endkatex %}

이것도 그림으로 보면 더 와닿을거에요.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/37rn3ldwymiursx3p0la.jpeg)

{% katex inline %}\eta{% endkatex %}도 Monoid로써 Identity를 만족시켜줘요.

근데 {% katex inline %}\mu{% endkatex %}가 대응되는 점과 비교해봤을때 이상한 점이 있죠. {% katex inline %}\mu{% endkatex %}도 함수고 {% katex inline %}\otimes{% endkatex %}도 함수니깐 짝궁이 맞다고 쳐도 {% katex inline %}\eta{% endkatex %}는 함수인데 Identity는 오브젝트잖아요!? 이점에대해서 설명하자면 {% katex inline %}\eta{% endkatex %}는 정확히는 모노이드의 오브젝트 x에 Identity 오브젝트를 곱해주는 (함수로 정의될 수 있는)행위 와 대응이 되는거에요. 즉 함수와 함수끼리 대응되는거라고 볼 수 있죠.

## 마무리

결론은 모나드는 파라메터 한개짜리 제네릭 타입의 모노이드에요. 이 글이 모나드/모노이드의 시야를 넓히는데 도움이 됐길 바래요.

이 토픽에 대한 더 자세하게 공부하고 싶다면 [Category Theory for Programmer - Monads Categorically](https://bartoszmilewski.com/2016/12/27/monads-categorically/) 를 추천해요.
전반적인 카테고리 이론에 대해 공부하고 싶다면
[Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/)
[Math3ma - Category Theory](https://www.math3ma.com/categories/category-theory)
개인적으로 푼 Category Theory for Programmers각 챕터 Challenges의 솔루션: [ingun37.github.io/answers/](https://ingun37.github.io/answers/?sha1=b614f31d04b3bc2b3d23ee4337475251429e5a9f)