저는 처음 모나드/모노이드를 배울때 누군가가 “모나드는 모노이드일 뿐이야” 라고 설명해줬으면 얼마나 좋았을까 생각해요. 그걸 알았다면 두개를 따로 따로 배우느라 시간낭비 하지 않았을텐데 하는 아쉬움이있어요. 생각해보니 대부분의 프로그래머를 위한 Monad 와 Monoid 학습 자료들을 보면 Monad의 경우 업계에서 Monad란 무엇인가?! 라는 주제의 글을 금지하고 있을정도로 깊이있는 탐구보단 프로그래머관점에서의 표면적인 이해를 위한 자료가 많아요. Monoid 도 마찬가지죠. 물론 프로그래머로써 이 둘을 깊게 이해할 필요는 없어요. 그 때문인지 이 둘이 독립적으로 다뤄질 때가 많아요.
이 글에서는 최대한 프로그래머 관점에서 쉽게 모나드를 모노이드로 설명하고, 모노이드로 정의를 내려봄으로써 독자가 이 두 토픽을 확실하게 이해할 수 있게끔 노력해볼거에요.
들어가기 앞서 둘이 같다는걸 이해하는것은 전혀 어렵지 않고 손뻗으면 닿는, 바로 눈앞에있다는것을 먼저 보여드릴게요
모양이 비슷하죠? 자세하게는 몰라도 둘이 같은걸 뜻한다는 느낌을 받을거에요.
모나드의 각 property들이 모노이드에 어떻게 대응하는지만 이해한다면 둘이 같은걸로 보이게 될거에요.
Monad <-> Monoid
프로그래머한테 모나드 T의 정의는 다음과같은 signature를 가진 두 함수의 존재에요.
μ(T2)→Tη(I)→T
프로그래머한테는 보통
μ
는 join으로,
η
는 return으로 많이 알려져 있죠.
T
는 모나드 타입이고
T2
는 모나드 타입
T
를 두번 적용 한 거에요. 모나드 List가
T
라면 List의 List가
T2
가 되겠죠.
물론 signature가 똑같다고 아무 함수나 되는건 아니에요. 만족해야하는 조건이 있어요. 하지만 이 조건을 컴파일러 레벨에서 강제할 수 있는 언어가 (제가알기론)없다보니 이름하야 monadic law는 프로그래머들에겐 무시당할 때가 많죠. 하지만 모나드가 모노이드라는 사실을 이해하기위해선 Monadic law 도 이해해야해요. 왜냐하면 Monadic Law는 두가지 (join의 룰, return의 룰)이 있는데 이 각각이 모노이드의 Associativity 와 Identity 에 대응이 되기 때문이에요.
모나드의 Join <-> 모노이드의 Associativity
μ
(혹은 join) 이 지켜야 하는 룰은 다음과 같아요
μ(T,μ(T2))=μ(μ(T2),T)
모나드 타입 (
T3
)를 T로 두번
μ
한다고 할때
μ(T2,T)
를 먼저 하든
μ(T,T2)
를 먼저 하든 결과는 똑같아야 한다는 뜻이에요. 다시 List로 예를 든다면 List<List<List>>.join().join()의 결과와 List<List<List>>.map(join).join()의 결과는 언제나 같아야 한다는 뜻이에요.
이 룰이 다음과같은 Monoid의 Associativity 에 대응해요.
(t1⊗t2)⊗t3=t1⊗(t2⊗t3)
그림으로 표현해보면 더 와닿을거에요
Monad의
μ
가 operator역할로 Monoid로써 Associativity 를 만족시켜줘요.
모나드의 세 T는 줄서서 하나의 타입으로 evaluate되길 기다리고 있어요. 양쪽 어느 쌍이 먼저 evaluate 되든 상관없어요 왜냐하면 monadic law 에 의해 결과는 똑같을것이기 때문이죠. 이 모나드의 property 는 모노이드의 associativity 와 대응돼요. 모노이드의 세 T는 줄서서 다른 algebraic value 로 evaluate 되길 기다리고있죠. 모노이드 역시 양쪽 어느 쌍이 먼저 evaluate 되든 상관없어요. 모노이드기 때문이죠.
모나드의 Return <-> 모노이드의 Identity
η
(혹은 return) 가 지켜야 하는 룰은 다음과 같아요
μ(η(I),T)=μ(T,η(I))
η
로 만든 T의 T든, T의
η
로 만든 T든
μ
를 적용했을 때의 결과값은 똑같아야 한다는 뜻이에요. 다시 List로 예를들면 List.map(return).join()의 결과와 return(List).join()의 결과는 같아야 한다는 뜻이에요.
이 룰은 Monoid의 Identity 에 대응해요
i⊗t=t⊗i=t
이것도 그림으로 보면 더 와닿을거에요.
η
도 Monoid로써 Identity를 만족시켜줘요.
근데
μ
가 대응되는 점과 비교해봤을때 이상한 점이 있죠.
μ
도 함수고
⊗
도 함수니깐 짝궁이 맞다고 쳐도
η
는 함수인데 Identity는 오브젝트잖아요!? 이점에대해서 설명하자면
η
는 정확히는 모노이드의 오브젝트 x에 Identity 오브젝트를 곱해주는 (함수로 정의될 수 있는)행위 와 대응이 되는거에요. 즉 함수와 함수끼리 대응되는거라고 볼 수 있죠.
마무리
결론은 모나드는 파라메터 한개짜리 제네릭 타입의 모노이드에요. 이 글이 모나드/모노이드의 시야를 넓히는데 도움이 됐길 바래요.
Top comments (0)