저번 post에서 Monoid와 Functor에 관해 이야기를 했다.
Functor는 어떤 box(higher-kinded type)에 함수를 적용 할 수 있는 방법을 가진 녀석이라고 했다.
그리고 Functor에 항등함수(Id)를 적용하면 원래의 Functor와 같으며, 두 함수를 합성한 후 Functor를 적용한 것은 한 함수에 Functor를 적용한 후의 Functor에 나머지 함수를 적용한 것과 같다고 했다.
scala 를 하면서 모나드, 모나드 무지 이야기가 나오는 것은 아마도 그만큼 중요 하기 때문일 것 이다. 이를 사용하면 코드 중복를 피하는 것 뿐아니라 for comprehension 표현으로 가능 함을 제공한다. 이제 Monad와 Monad를 구성하는 함수set들을 살펴 보자.
(함수와 메소드는 다르지만 설명을 위해 구분을 따로 하지 않고 함수라 표현 했다.)
Monad
Functor가 어떤 box에 함수적용을 알고 있는 것이라면 Monad는 함수를 적용하고 다시 box에 담는 것이라 할 수 있다. 따라서 결과를 다시 모나드로 보낼 수 있다.
위의 정의만 봐서는 Monad는 Functor이기도 함을 알 수 있다. 아래에 flatMap과 unit( 함수 이름을 unit보다는 pure로 많이 표현함.)로 map을 구현 할 수 있다. 추후 적용함수도 구현 가능 하다.
우선 box에 값을 꺼내어 함수를 적용하는 것을 Functor 라 했고 표현을 아래와 같이 했다.
그러면 Monad는 box에서 값을 꺼내 함수를 적용하고 다시 box에 담는 것이니 아래와 같이 표현하면 될 듯 하다.
f를 보면 box의 값에서 f를 적용하면 결과로 다시 box인 F[B]로 반환 한다.
Monad를 typeclass로 나타내면 다음과 같다.
Monoid, Functor도 법칙이 있 듯 물론 Monad도 법칙이 있다.
Monad Law
1.Left 항등법칙 2.Right 항등법칙 3.bind함수에 대한 결합법칙
Left 항등법칙
Right 항등법칙
flatMap 연산에 대한 결합법칙
Monad 의 적용 결과는 모나드의 입력으로 그결과는 또다른 입력으로 Monad chain이 가능하다.
Monad는 행간의 무었이 일어나느지 명시하는 것이 아닌, 단지 어떤 일이 일어나더라도 그것이 결합법칙과 항등법칙을 만족함을 명시할 뿐이다.
Monad 의 다른 조합 유형
compose
어떤 higher-kinded type이 위의 Monad법칙을 만족시키고 다음과 같은 bind operator를 가진다면 Monad라 할 수 있다.
flatMap[B](f: A => F[B]): F[B]
그럼 또 하나의 아래와 같은 signatuer를 보자
위와 같은 함수로 flatMap를 구현 할 수 있을까? 아래 코드를 보자
가능하다. 그럼 Monad의 구성 set은 unit 과 compose 구성으로 가능한 또 하나의 구성이 생긴다.
flatten
위의 Monad 정의에서 Monad는 Functor이기도 하다라고 했다. 그렇다면 Monad의 구성 set으로 map함수를 만들 수 있어야 한다. map함수는 다음과 같았다.
이를 unit과 flatMap 으로 아래와 같이 구현 할 수 있다.
이제 Monad는 Functor 임을 알 수 있다.
다음으로 flatten이라는 다음과 같은 함수가 있다고 하자.
자 그럼 map과 flatten으로…
맞다 flatMap을 구현 할 수 있다.
이로써 Monad의 또 하나의 구성이 되었다.
unit, flatMap
unit, componse
unit, flatten
Monad의 합성? (Composed Monad ?)
Monad의 합성을 해볼까? 즉 Monad F 와 Monad G의 합성으로 된 F[G[_]]인 Monad를 해볼까?
될까? 안될까?
무작정 시도 해보자
여기에 나오는 context bound 및 람다type(#f는 f[x]에 대한 type project, f[x]는 type F[G[x]] 를 나타 낸다.)은 나중에..
위에 G.map(ga)(f)의 결과는 G[F[G[B]]]이다….
이를 위해서는 sequence[A](ma: F[G[A]]):G[F[A]]가 필요하다.. 이는 추후 Traverse 순회적용함수자에서 보고 여기서 Monad post를 마친다.