Skip to content

Latest commit

 

History

History
383 lines (226 loc) · 23.5 KB

22_Monads_Categorically.md

File metadata and controls

383 lines (226 loc) · 23.5 KB

22. Monads Categorically

만일 모나드를 프로그래머에게 말한다면 아마 사이드 이펙트를 중점으로 이야기할것 입니다. 수학자에게 모나드는 대수학에 대한 주제입니다. 대수학에 대해서는 나중에 이야기 할것 입니다. - 이는 프로그래밍에서 매우 중요한 역할을 합니다 - 하지만 우선 모나드와의 관계에서 몇가지 통찰을 주려고합니다.

대수학은 만들어내거나, 조작하거나 수식을 평가하는것에 대한것 입니다. 수식은 연산자를 이용해 만들어 집니다. 예를들어 이 수식을 보세요.

𝑥^2 + 2𝑥 + 1

이 수식은 변수 x, 상수 1혹은 2 그리고 이들간의 더하기 혹은 제곱 연산다로 이루어져 있습니다. 프로그래머로서 우리는 종종 수식을 트리로 생각합니다.

트리는 컨테이너 이기에, 더 일반적으로, 수식은 값을 담는 컨테이너 입니다. 카테고리 이론에서 컨테이너를 엔도펑터로 나타냈습니다. 변수 x에 타입 a를 대입한다면 위 수식은 타입 m a를 지니게 되고 여기서 m은 수식 트리를 구성하는 엔도펑터 입니다. (가지를 나타내는 수식은 대게 재귀적으로 정의된 엔도펑터로 만들어집니다.)

수식에서 가장 많이 사용할 수 있는 연산은 무엇일까요? 치환입니다: 변수를 수식으로 치환말입니다. 예를들어 위의 수식에서 X를 y - 1로 치환하면 다음을 얻을 수 있습니다.

(y - 1)^2 + 2(y - 1) + 1

보십쇼: 우리는 m a 타입의 수식을 가져와 a -> m b 타입의 치환을 적용했습니다.(b는 y 타입을 나타냄). 결과는 m b 타입의 표현식 입니다.

m a -> (a -> m b) -> m b

그렇습니다. 이것은 모나딕 바인드의 시그니처 입니다.

이제 모나드의 수학으로 가보죠. 수학자들은 프로그래머와 다른 노테이션을 사용합니다. 엔도펑터에는 𝑇, join은 그리스 문자 𝜇 그리고 return 에는 𝜂를 사용합니다. join과 return 모두 다형성 함수이기때문에 이들은 자연변환에 해당합니다.

그러므로 카테고리이론에서 모나드는 𝜇, 𝜂 쌍을 지닌 엔도펑터 T로 정의됩니다.

𝜇는 T^2 -> T인 자연변환 입니다. 제곱은 𝑇 ∘ 𝑇를 뜻합니다.(이는 엔도펑터에만 가능합니다.)

𝜇∷𝑇^2→𝑇

대상 a에 대한 이 자연변환의 컴포넌트는 다음과 같은 사상입니다.

𝜇a∷𝑇(𝑇a)→𝑇a

이는 하스켈에서 join으로 나타낼 수 있습니다.

𝜂는 아이덴티티 펑터 I와 T간의 자연변환 입니다.

𝜂∷𝐼→𝑇

대상 a에 대한 I는 단지 a이기에 이에대한 컴포넌트는 다음과 같은 사상입니다.

𝜂a∷a→𝑇a

그리고 이는 하스켈에서 return의 정의와 동일합니다.

이 자연변환들은 추가적인 법칙을 만족하여야합니다. 이를 볼 수 있는 한가지 방법은 이 법칙이 엔도펑터 T를 클라이슬리 카테고리로 만들어준다는 점 입니다. a, b간의 클라이슬리 화살표가 a -> Tb와 같은 사상으로 정의됨을 기억하세요. 이 두 화살표간의 합성은 𝜇로 구현될 수 있습니다.(I’ll write it as a circle with the subscript 𝑇)

𝑔 ∘𝑇 𝑓 = 𝜇𝑐 ∘ (𝑇 𝑔) ∘ 𝑓

where

f :: a -> T b

g :: b -> T c

// 대충 f를 T로 리프팅한거를 g랑 합성하고 join으로 평탄하게해서 T c 라는듯

우변에서 T 펑터를 g에 적용하는것으로 시작하는데 아래의 하스켈 코드로 쓰는게 더 쉬울것입니다.

f >=> g = join . fmap g . f
-- or, 컴포넌트에 대하여
(f >=> g) a = join (fmap g (f a))

대수학적 해석의 관점에서 우리는 두개의 연속적인 치환을 구성하고 있습니다.

클라이슬리 화살표가 카테고리를 형성하기 위하여 이들의 합성이 결합법칙을 만족해야하고 𝜂𝑎는 a에 대한 클라이슬리 화살표의 identity가 되어야 합니다. 이 요구사항은 𝜇, 𝜂에 대한 모나드의 법칙으로 해석될 수 있습니다. 하지만 이 법칙이 모노이드 법칙과 비슷하게 보이게하는 다른 방법이 있습니다.사실상 𝜇 은 종종 multiplication 그리고 𝜂는 unit 이라 불립니다.

대략적으로 말하면 교환법칙은 𝑇, 𝑇^3 큐브를 T로 줄이는 두가지 방법이 동일한 결과를 제공해야함을 의미합니다. 두개의 단위 법칙(왼쪽과 오른쪽)은 𝜂가 T에 적용된 다음 𝜇로 감소하여 다시 T로 돌아옴을 의미합니다.

이는 약간 교묘한데요, 이는 자연변환과 펑터를 합성하기 때문 입니다. 그렇기에 수평적 합성에 대하여 다시 상기해 봅시다. 예를들어 T^3는 T^2 이후의 T의 합성에서 볼 수 있습니다. 우리는 이를 두개의 자연변환의 합성에 적용할 수 있습니다.

𝐼𝑇 ∘𝜇

그러면 𝑇 ∘ 𝑇를 얻습니다. 그리고 이는 𝜇를 적용하여 𝑇로 줄어들 수 있습니다.𝐼𝑇 는 T에서 T로 가는 아이덴티티 자연변환 입니다. 수평적 합성 𝐼𝑇 ∘ 𝜇 노테이션이 𝑇 ∘ 𝜇로 줄어드는 것을 자주 보게될 것 입니다. 이 노테이션은 펑터와 자연변환을 합성하는것은 말이 안되기 때문에 애매하지 않습니다?(This notation is unambiguous because it makes no sense to compose a functor with a natural transformation) 그러므로 T는 이 문맥에서 𝐼𝑇를 의미하여야 합니다.

또한 카테고리 (엔도) 펑터 카테고리 [C, C]의 다이어 그램을 그릴 수 있습니다.

T^3를 T^2 ∘ T 합성으로 치부할 수 있고 여기에 𝜇∘𝑇를 적용할 수 있습니다. 이 결과는 역시 T ∘ T 일것이고 다시 여기에 𝜇을 이용하여 T를 얻을 수 있습니다. 두 경로가 동일한 결과를 생성해야만 합니다.

비슷하게 수평적 합성 𝜂 ∘ 𝑇을 T 이후 아이덴티티 펑터 I의 합성에 적용하여 T^2를 얻을 수 있고 이는 다시 𝜇로 줄어들어 T가 될 수 있습니다. 이 결과는 먼저 보았던 T에 바로 아이덴티티 자연변환을 적용하였을 경우와 동일해야합니다. 그리고 유사성에 의하여 𝑇 ∘ 𝜂의 경우에도 마찬가지 입니다.

이 법칙이 클라이슬리 화살표 합성이 참으로 카테고리의 법칙을 만족함을 장담할 수 있습니다.

모나드와 모노이드의 유사함은 놀랍습니다. 곱에 해당하는 𝜇, 유닛에 해당하는 𝜂, 결합법칙, 유닛 법칙이 만족합니다. 하지만 우리가 모노이드를 정의했던것은 모나드를 모노이드로 묘사하기에는 다소 편협적 입니다. 그렇기에 이제 모노이드의 개념을 보다 일반화 해 봅시다.

22.1 Monoidal Categories

편의를 위해 모노이드에 대해 정의하였던 부분으로 다시 돌아가 봅시다. 이는 이항 연산자와, 유닛이라 불리는 특별한 원소의 집합이였습니다. 하스켈에서 이는 다음과 같이 typeclass로 표현될 수 있습니다.

class  Monoid m where 
mappend :: m -> m -> m
mempty :: m

이항연산자 mappend는 결합법칙과 unital을 만족해야 합니다.

하스켈에서 mappend의 정의가 커링이 이용되었음에 주목하세요. 이는 모든 원소 m을 함수로 매핑하는것으로 다음과 같이 해석될 수 있습니다.

mappend :: m -> (m -> m)

이 해석은 모노이드의 정의를 하나의 대상을 지니고 endo사상 (m -> m)이 모노이드의 원소를 나타내는 카테고리라는것으로 이끕니다. 하지만 커링은 하스켈에 기본내장되어있기때문에(이말이 갑자기 왜나와..), multiplication의 정의를 다르게 시작할 수 있습니다.

mu :: (m, m) -> m

여기서 카르테시안 곱 (m, m)은 multiplied 되기위한 쌍의 소스가 됩니다.

이 정의는 다른 방식의 일반화를 이끕니다: 카르테시안 곱을 카테고리적인 곱으로 바꾸는거 말입니다. 곱이 전역적으로 정의된 카테고리에서 시작하여 대상 m을 골라 multiplication을 사상으로 정의할 수 있습니다.

𝜇∷𝑚×𝑚→𝑚

여기에 약간의 문제가 있는데 이 임의의 카테고리에서 우리는 대상의 내부에서 원소를 골라낼 수 없습니다.(mxm에서 m을 골라낼수없다는거인듯) 그러면 어떻게 유닛 엘리먼트를 골라낼까요? 여기에 트릭이 있습니다. 원소의 선택이 싱글톤셋에서 출발하는 함수와 비슷하다는것을 기억하세요. 하스켈에서 mempty의 정의를 다음과 같은 함수로 대체할 수 있습니다.

eta :: () -> m

싱글톤은 Set에서 터미널 오브젝트 입니다. 그렇기에 터미널 오브젝트 t를 지니는 모든 카테고리에 대하여 이를 일반화 하는것은 자연스럽습니다.

𝜂∷𝑡→𝑚

이는 원소에 대해 말할필요 없시 유닛 원소를 골라내는 방식 입니다.

대상이 하나라는 이전에 정의한 모노이드의 정의와 달리 지금은 모노이드적 법칙이 자동적으로 만족되지 않습니다 - 그러기에 이를 부여하여야 합니다. 그러나 그것 이전에 우리는 깔려있는 카테고리적 곱의 모노이드적 구조를 먼저 확립해야 합니다. 우선 하스켈에서 모노이드적 구조를 어떻게 작동하는지 먼저 봅시다.

mu (x, mu (y, z)) = mu (mu (x, y), z)

이를 다른 카테고리로 일반화 하기 전에, 함수의(사상)의 동등함을 다시 써야 합니다. 함수가 각각의 변수에 작동하는것에서 벗어나 이를 추상화하여 - 다시말해서 우리는 point-free 노테이션을 이용하여야만 합니다. 카르테시안 곱은 바이펑터이기 때문에 좌변과 우변을 다음과 같이 쓸 수 있습니다.

-- bimap f g = first f . second g

-- 좌변
(mu . bimap id mu)(x, (y, z))

-- 우변
(mu . bimap mu id)((x, y), z)

이는 거의 우리가 원하는것과 같지만 카르테시안 곱은 엄격하게 교환법칙이 성립하지 않습니다. - (x, (y, z))는 ((x, y), z)와 같지 않습니다. - 그래서 point-free를 사용할 수 없습니다.

mu . bimap id mu = mu . bimap my id

반면에 두 쌍의 중접은 동형입니다. 그들 사이에는 associator라 불리는 다음과같이 역이존재하는 함수가 있습니다.

alpha :: ((a, b), c) -> (a, (b, c))
alpha :: ((x, y), x) = (x, (y, z))

associator로 인해 mu에 대한 결합법칙을 point-free로 쓸 수 있습니다.

mu . bimap id mu . alpha = mu . bimap mu id

Unit 법칙에서도 동일한 트릭을 사용하여 다음과 같은 새로운 노테이션을 얻을 수 있습니다.

mu (eta (), x) = x
mu(x, eta ()) = x

이들은 이제 다음과 같이 다시쓸 수 있습니다.

(mu . bimap eta id) ((), x) = lambda((), x)
(mu . bimap id eta) (x, ()) = rho (x, ())

동형사상 lambda, rho는 각각 left, right unitor로 불립니다. 그들은 유닛 ( )가 동형에 이르기까지 카르테시안 곱의 아이덴티티가 동형이라는것을 확인합니다.(They witness the fact that the unit () is the identity of the Cartesian product up to isomorphism:)

lambda :: ((), a) -> a
lambda ((), x) = x

rho :: (a, ()) -> a
rho (x, ()) = x

그러므로 unit law의 point-free 버전은 다음과 같습니다.

mu . bimap id eta = rho
mu . bimap eta id = lambda

깔려있는 카르테시안 곱 자체가 타입 카테고리에서 모노이달 곱 처럼 작동한다는 사실을 사용하여 mu및 eta에 대한 point-free unit laws를 공식화 하였습니다. 카르테시안 곱에 대한 결합법칙 및 unit law는 동형에 따라 유효하다는 점에 주의하세요.

이제 이 법칙은 곱과 터미널 오브젝트가 있는 카테고리에 일반화 할 수 있다는 것을 알 수 있습니다. 카테고리적 곱은 동형에 따라 결합법칙을 만족하고 터미널 오브젝트가 유닛 입니다. associator와 두개의 unitors는 자연변환 입니다. 이 법칙은 다음과 같은 가환 다이어그램으로 나타낼 수 있습니다.

곱은 바이펑터 이기 때문에 사상의 쌍도 리프팅 할 수 있다는 점에 유의하세요 - 하스켈에서 이는 bimap으로 구현됩니다.

카테고리적 곱과 터미널 오브젝트를 이용하여 모든 범주 위에 모노이드를 정의할 수 있다 정의하고 여기서 멈출 수 있습니다. 대상 m과 사상 𝜇, 𝜂을 골라낼 수 있다면 이들은 모노이드 법칙을 만족하고, 우리는 모노이드를 얻을 수 있습니다. 하지만 이보다 더 할 수 있습니다. 𝜇 및 𝜂에 대한 법칙을 공식화하기위해 본격적인 카테고리적 곱이 필요하지 않습니다. 곱이 프로젝션을 이용해 universal construction을 통하여 정의했던것을 기억하세요. 우리는 아직 모노이달 법칙의 공식에 프로젝션을 이용하지 않았습니다.

곱과 비슷한 역할을 하지만 곱이 아닌 바이펑터는 tensor product라 불리고 종종 인픽스 연산자 ⊗로 인용됩니다. Tensor product의 일반적인 정의는 약간 어렵지만 걱정하지 마세요. 여기서는 단지 그 특성들을 열거할것입니다. - 제일 중요한점은 동형에따라 결합법칙을 만족한다는 점 입니다.

비슷하게 t가 터미널 오브젝트일 필요는 없습니다. - 터미널 속성을 사용하지 않았었습니다. - 즉 대상에서 대상으로 고유한 사상이 존재한다는 점 입니다.(Similarly, we don’t need the object 𝑡 to be terminal. We never used its terminal property — namely, the existence of a unique morphism from any object to it) 우리에게 필요한점은 tensor product와 함께 동작하여야한다는 점 입니다. 동형에따라 텐서곱의 유닛이 되면 된다는 것입니다. 이를 모두 합쳐 봅시다:

모노이달 카테고리는 텐서 곱이라 불리는 바이펑터를 지니는 카테고리 C 입니다.

⊗∷𝐂×𝐂→𝐂

그리고 개별 대상 i는 각각 associator, left, right unitors라 불리는 3가지의 자연적인 동형사상과 함께 유닛 오브젝트 입니다.

𝛼𝑎𝑏𝑐 ∷(𝑎⊗𝑏)⊗𝑐→𝑎⊗(𝑏⊗𝑐)

𝜆𝑎 ∷ 𝑖 ⊗ 𝑎 → 𝑎

𝜌𝑎 ∷ 𝑎 ⊗ 𝑖 → 𝑎

중요한점은 텐서곱이 많은 바이펑터를 설명한다는 점 입니다. 특히 product, coproduct, 그리고 곧 보게될 엔도펑터의 합성에 대하여 동작합니다. 모노이달 카테고리는 풍부한 카테고리의 공식에서 중요한 역할을 합니다.

22.2 Monoid in a Monoidal Category

이제 모노이드의 범주보다 보다 일반적인 설정에서 모노이드를 정의할 준비가 되었습니다. 어떤 대상 m을 선택하는것부터 시작합시다. 텐서곱을 이용하여 m의 제곱(powers) 형성할 수 있고, m의 제곱근(square)는 𝑚 ⊗ 𝑚 입니다. m의 큐브를 형성하는 방식에는 두가지가 있습니다. 하지만 이들은 associator에 의하여 동형입니다. 비슷하게 m의 더 큰 제곱은 모노이드를 형성하려면 두가지 사상이 있어야합니다.

𝜇∷𝑚⊗𝑚→𝑚

𝜂∷𝑖→𝑚

여기서 i는 텐서곱의 유닛 오브젝트 입니다.

이 사상들은 결합법칙과 유닛 법칙을 만족하여야하고 다음과 같은 가환 다이어그램으로 나타낼 수 있습니다.

사상의 쌍을 리프팅하여 𝜇 ⊗ id나 𝜇 ⊗ id를 형성하기 위해 텐서 곱이 바이펑터 이여야한다는 점을 주목하세요. 이 다이어그램들은 일전에 얻었던 카테고리적 곱을 간단하게 일반화 한 것입니다.

22.3 Monads as Monoids

모노이드적 구조는 예상하지 않은 부분에서 찾을 수 있습니다. 한가지 예는 펑터 카테고리에서 이를 찾을 수 있다는 점 입니다. 여기서 펑터 합성이 multiplication를 형성한다는 것을 볼 수 있을것입니다. 문제는 항상 두 펑터가 합성 가능하지 않다는 점 입니다. - 합성하려는 하나의 펑터의 타겟 카테고리는 다른 펑터의 소스와 일치해야 합니다. 이는 사상의 합성을 위한 일반적인 조건과 유사합니다 - 그리고 실제로 펑터는 Cat 카테고리에서 사상입니다. 하지만 endomorphisms(동일한 대상으로 돌아오는 사상)은 언제나 합성할 수 있고 엔더펑터도 마찬가지 입니다. 주어진 카테고리 C에 대하여 C에서 C로 가는 엔도펑터는 [C, C] 카테고리를 형성힙니다. 이 카테고리의 개상은 엔도펑터이고 사상은 이들간의 자연변환 입니다. 이 카테고리에서 임의의 대상 F, G를 선택하여 세번째 대상 F . G(합성에 따라 만들어진 엔더펑터)를 만들어 낼 수 있습니다.

엔도펑터의 합성은 텐서 곱의 좋은 후보자일까요? 우선 그것이 바이펑터임을 입증 하여야합니다. 이것이 사상을 리프팅할 수 있나요? - 여기서는 자연변환을? 대략적으로 텐서곱의 bimap 시그니처는 다음과 같이 나타낼 수 있을것입니다.

𝑏𝑖𝑚𝑎𝑝 ∷ (𝑎 → 𝑏) → (𝑐 → 𝑑) → (𝑎 ⊗ 𝑐 → 𝑏 ⊗ 𝑑)

대상을 엔도펑터로, 화살표를 자연변환으로 바꾼다면 합성에 따른 텐서곱은 다음과 같이 나타낼 수 있습니다.

(𝐹 → 𝐹′) → (𝐺 → 𝐺′) → (𝐹 ∘ 𝐺 → 𝐹′ ∘ 𝐺′)

이를 수평적 합성에서 많이 봤었죠?

또한 엔도펑터의 합성(새로운 텐서곱)에 단위 역할을 하는 아이덴팉티 엔도펑터 𝐼 를 사용할 수 있습니다. 더욱이 펑터의 합성은 결합법칙을 만족합니다. 사실상 결합법칙과 유닛 법칙이 만족하기떄문에 더이상 associator와 두개의 unitors가 필요하지 않습니다. 따라서 엔도펑터는 텐서곱으로서 펑터 합성과 함께 엄격한 모노이달 카테고리를 형성합니다.

이 카테고리에서 모노이드는 무엇일까요? 이는 대상이고 엔토펑터 T 입니다. 그리고 두개의 사상은 자연변환 입니다.

𝜇∷𝑇∘𝑇→𝑇

𝜂∷𝐼→𝑇

이와함께 모노이드 법칙도 존재합니다.

이는 위에서 보았던 모노이드 법칙과 정확하게 일치합니다. 이제 Saunders Mac Lane의 유명한 인용문을 이해할 수 있습니다.

All told, monad is just a monoid in the category of endofunctors.

모나드는 엔도펑터 범주에서 모노이드일 뿐 입니다.

22.4 Monads from Adjunctions

수반 𝐿 ⊣ 𝑅 은 카테고리 C, D 사이에서 왔다갔다할 수 있는 펑터의 쌍 입니다. 이들을 합성하는 2가지 방법 𝑅 ∘ 𝐿, 𝐿 ∘ 𝑅이 있고 이는 엔도펑터를 만들어 냅니다. 수반에 따르면 이러한 엔도펑터는 unit과 counit이라는 두가지 자연변환을 통해 아이덴티티 펑터와 관련이 있습니다.

𝜂∷𝐼𝐃 →𝑅∘𝐿

𝜀 ∷ 𝐿 ∘ 𝑅 → 𝐼𝐂

즉시 수반의 유닛이 모노이드의 유닛과 비슷하다는 것을 볼 수 있습니다. 엔도펑터 𝑅 ∘ 𝐿은 모나드임이 들어납니다. 이제 필요한건으 적절한 μ와 η 입니다. 이들은 엔도펑터의 곱과 엔도펑터 자체의 자연변환 입니다.

𝑅∘𝐿∘𝑅∘𝐿→𝑅∘𝐿

그리고 중간의 𝐿 ∘ 𝑅을 counit으로 사용할 수 있습니다. 𝜇의 정확할 공식은 수평적 합성을 제공됩니다.

𝜇=𝑅∘𝜀∘𝐿

모나드적 법칙은 수반과 교환 법칙의 unit과 counit을 만족하는 아이덴티티를 따릅니다(Monadic laws follow from the identities satisfied by the unit and counit of the adjunction and the interchange law.)

하스켈에서 모나드가 수반에서 파생되는것을 보지는 못했었습니다. 이는 수반은 종종 두개의 카테고리를 포함하기 때문입니다. 하지만 익스포넨셜이나 함구 객체의 정의는 예외입니다. 다음은 수반을 형성하는 두개의 엔도펑터 입니다.

𝐿 𝑧=𝑧×𝑠

R b = s => b

이들의 합성을 상태 모나드에서 익숙하게 봤었습니다.

R(L z) = s -> (z x s)

newtype State s a = State (s -> (a, s))

수반을 하스켈로 표현해 봅시가. left 펑터는 product 펑터이고 right 펑터는 리더 펑터입니다.

newtype Prod s a = Prod (a, s)
newtype Reader s a = Reader (s -> a)

instance Adjunction (Prod s) (Reader s) where
	couint (Prod (Read f, s)) = f s
	unit a = Reader (\s -> Prod (a, s))

product 펑터 이후 리더 펑터의 합성은 상태 펑터임이 보일것 입니다.

newtype State s a = State(s -> (a, s))

예상하는바와 같이 수반의 unit은 상태 모나드의 return에 대응됩니다. 그리고 counit은 그것의 아규먼트에 작용하는 함수를 evaluating 하여 동작합니다. 이것은 runState 함수의 언커링 버전으로 인식할 수 있습니다.

runState :: State s a -> s -> (a, s)
runState (State f) = f s

이제 상태 모나드를 위한 join을 자연변환 𝜇의 컴포넌트로 정의할 수 있습니다. 이를 위하여 3개 자연변환의 수평적 합성이 필요합니다.

𝜇=𝑅∘𝜀∘𝐿

다시말해 counit 𝜀를 리더펑터 수준으로 숨겨야 합니다. 컴파일러가 리더 펑터가 아닌 상태 펑터를 선택하기때문에 fmap을 바로 호출할 수 없습니다. 하지만 리더펑터의 fmap은 좌측함수의 합성 이라는 점을 기억하세요. 그렇기에 함수합성을 바로 사용할것입니다.

먼저 데이터 생성자 State를 벗겨내어 State 펑터 내부의 함수를 노출해야 합니다. 이것은 runState로 수행할 수 있습니다.

ssa :: State s (State s a)
runState ssa :: s -> (State s a, s)

그런이후 uncurry runstate에 의해 정의되는 counit으로 좌측 합성을 합니다. 마지막으로 다시 State 데이터 생성자에 입힙니다.

join :: State s (State s a) -> State s a
join ssa = State (uncurry runState . runState ssa)

이는 실제 상태 모나드의 join 구현입니다.

이는 모든 수반이 모나드를 형성하고 그 역도 마찬가지임을 보입니다. 모든 모나드는 두개의 adjoint 펑터의 합성으로 분리될 수 있습니다. 하지만 이러한 분해는 고유하지 않은데 다음 섹션에서 다른 엔도펑터 𝐿 ∘ 𝑅에 대하여 이야기할것 입니다.