Monads in Java라는 글을 읽고 처음으로 monad라는 개념을 접하게 되었습니다. 이 글에서는 monad에 대해 다음과 같이 정의합니다.
We can think of monads as containers that allow us to handle the effects outside the function’s scope, preserving the function’s purity.
"모나드는 함수의 순수성을 유지하면서 함수의 범위 밖의 효과를 처리할 수 있는 컨테이너로 생각할 수 있다"
이 설명만으로 볼 때 monad라는 개념은 너무 추상적이어서 이해하기가 어려웠습니다.
monad가 무엇인지 좀 더 깊게 이해하고자 여러 내용을 찾아보았는데 한 가지의 개념을 다양하게 설명하고 있는 것을 알게 되었습니다. 이런 부분이 흥미로워 정리하는 글을 작성하게 되었습니다.
가장 먼저 StackOverflow에 monad에 무엇인지에대해 검색해보니 다양한 논의가 이루어진 글이 있었습니다.
추천을 가장 많이 받은 내용들을 정리해보니 다음과 같은 개념으로 설명하고 있었습니다. (자세한 내용은 링크를 통해 참고하세요!)
They are a pattern for chaining operations. It looks a bit like method chaining in object-oriented languages, but the mechanism is slightly different.
What is a monad? The short answer: It's a specific way of chaining operations together.
Monads are simply a way to wrapping things and provide methods to do operations on the wrapped stuff without unwrapping it.
A monad is a function composition technique that externalizes treatment for some input scenarios using a composing function, bind, to pre-process input during composition.
A monad is, effectively, a form of "type operator". It will do three things. First it will "wrap" (or otherwise convert) a value of one type into another type (typically called a "monadic type"). Secondly it will make all the operations (or functions) available on the underlying type available on the monadic type. Finally it will provide support for combining its self with another monad to produce a composite monad.
키워드를 요약해본 결과 아래와 같이 4개의 개념으로 표현이 되고 있었습니다.
이 외에도 함수형 프로그래밍 언어 Haskell에서는 monad에서 다음과 같이 정의하고 있습니다.
In short, a monad is a way to structure computations in terms of values and sequences of computations using typed values
Haskell에서는 monad는 값을 사용한 연산과 연산의 순서를 구조화하는 방법이라고 말합니다.
monad는 3가지 규칙이 존재합니다.
Monad.of(x).flatMap(y -> f(y)) = f(x)
monad.flatMap(y -> Monad.of(y)) = monad
monad.flatMap(x -> f(x)).flatMap(x -> g(x)) = monad.flatMap(x -> f(x).flatMap(x -> g(x)))
이러한 monad 3원칙을 통해 monad는 메소드 체이닝을 통한 연산 형식을 제공할 수 있다.는 것을 알 수 있습니다.
return :: a -> M a
bind :: (M a) -> (a -> M b) -> (M b)
여기까지 봤을 때 Monad 패턴을 적용하기 위해서는 3가지 법칙과, 2가지의 operator를 제공할 수 있도록 해야 한다는 것을 알 수 있습니다.