이 장에서는 함자 사이의 사상인 자연 변환을 소개하고, 이를 통해 범주의 동치와 자연 동형, 그리고 프로그래밍에서의 다형 함수와의 연결을 살펴본다.
나는 함자를 연구하기 위해 범주를 발명한 것이 아니다. 자연 변환을 연구하기 위해 범주를 발명했다. — Saunders Mac Lane
이 장에서는 함자 사이의 사상, 즉 _자연 변환_의 개념을 소개하겠습니다. 자연 변환을 이해하면 범주의 같음과 몇 가지 다른 고급 개념을 정의할 수 있게 됩니다.
자연 변환은 실제로 범주론의 핵심에 있습니다. 하지만 그 중요성은 처음에는 분명하지 않습니다. 그래서 이를 소개하기 전에, 이 심장이 유지하고 있는 지식의 몸체에 대해 다시 한 번 이야기하고 싶습니다(나는 비유를 잘합니다… 원칙적으로는요).
첫 번째 절의 목표는 두 범주가 같다고 말하는 방법을 만들기 위한 동기 부여 예시로서 자연 변환을 소개하는 것입니다. 하지만 그러기 위해서는 먼저 범주가 같다는 것이 무엇인지, 또 무엇이어야 하는지를 이해해야 합니다.
그럼, 동치인 범주와 자연 변환에 대해 들을 준비가 되었나요? 사실 제 생각에는 아직 준비가 안 되셨습니다(기분 나쁘게 들으실 필요는 없습니다. 그냥 정말 어렵거든요!). 그래서 우리는 좀 더 먼 길로 가겠습니다. 다음 절은 이 책의 어디에 넣어도 어딘가 어정쩡한 위치가 될 것입니다. 그래도 어쨌든, 수학을 공부하고 있다면 아마 _우주의 본성_에 관심이 있을 것입니다. “이 세계의 모든 것의 가장 본질적인 특징은 무엇인가?” 하고 여러분이 묻는 소리가 들리는군요…
세계는 사물들의 집합이 아니라 사실들의 집합이다. — Ludwig Wittgenstein
이 세계의 모든 것의 가장 본질적인 특징은 무엇일까요? 약 2500년 전, 철학자 Parmenides는 이 질문에 답을 제시하며 우주의 본성은 지속성, 정지 상태라고 주장했습니다. 그의 관점에 따르면 우리가 과정/변형/변화로 지각하는 것은 단지 환영에 불과한 겉모습입니다(“있는 것은 있고, 없는 것은 있을 수 없다”). 그는 사물은 결코 실제로 변하지 않고, 단지 변하는 것처럼 보일 뿐이라고 말했습니다. 또는 다른 식으로 말하면, 변하는 것은 겉모습뿐이고 _본질_은 변하지 않는다는 것입니다(“본질”이라는 말이 생겨난 것도 대체로 이런 맥락이 아닐까 싶습니다).
그의 견해가 자명하게 참인 것은 아니지만, 사람들은 그것에 쉽게 공감합니다. 대상은 우리 주변 어디에나 있고, 우리가 “보는” 모든 것, 문자 그대로의 현실이든 비유적인 의미의 수학과 다른 학문이든, 모두 _대상_으로 볼 수 있으며 공간과 시간을 가로질러 지속됩니다. 만약 우리가 이런 관점을 따른다면, 세계를 이해하는 열쇠는 _대상이 무엇인지_를 이해하는 것이라고 생각하게 될 것입니다. 제 생각에는 집합론이나 고전 논리가 어느 정도는 이런 일을 합니다(Plato는 형상 이론을 만들 때 Parmenides의 영향을 받았습니다).
하지만 우주의 본성에 대한 질문에 접근하는 또 다른 길도 있으며, 그 또한 매우 설득력 있습니다. 왜냐하면 대상은 그 자체로 보면 무엇일까요? 대상을 고립된 상태로 연구할 수 있을까요? 그리고 어떤 대상이 환경으로부터 떼어졌을 때, 거기에는 더 연구할 것이 남아 있을까요? 어떤 대상이 과정을 거쳐 그 모든 부분이 교체되었다면, 그것은 여전히 같은 대상일까요?
이런 질문을 던지다 보면, 우리가 우주를 바라볼 때 보는 것은 대상이지만, 실제로 우주를 이해하는 열쇠는 대상들 사이의 과정/관계/전이, 즉 _사상_이라는 의심이 들게 됩니다. 예를 들어 일상적인 사물을 곰곰이 생각해 보면, 각각은 고유한 _기능들_을 가지고 있고(이 용어에 주목하세요), 그 기능 없이는 그 사물은 자기 자신일 수 없습니다. 예를 들어 빛나지 않는 램프는 여전히 램프일까요? 먹을 수 없는 음식이 있을까요(혹은 음식이 아닌데 먹을 수 있는 것이 있을까요)? 그리고 이것은 수학적 대상에 대해서는 더욱더 맞는 말입니다. 대상들 사이를 오가는 함수들이 없다면, 수학적 대상은 아예 대상이라고 할 수도 없기 때문입니다.
그래서 우리는 단지 사상들이 몇 개 붙어 있는 대상으로 생각하는 대신, 정반대의 관점을 취해 _대상은 오직 사상의 출발점과 도착점으로서만 흥미롭다_고 말할 수 있습니다.
이 관점은 오래되었고, Parmenides의 경쟁자로 알려진 Heraclitus까지 거슬러 올라가지만, 20세기 전까지는 거의 탐구되지 않았습니다. 그러다가 진짜 수학적 혁명이 일어났습니다. Bertrand Russell이 타입 이론을 만들었고, 그의 제자 Ludwig Wittgenstein은 위의 인용문이 나온 작은 책을 썼으며, 그 책은 “Vienna circle”로 알려진 수학자와 논리학자 집단에 영감을 주었습니다. 그리고 이 집단의 일원이었던 Rudolph Carnap이 “functor”라는 단어를 만들었습니다…
범주론의 영역에서 Heraclitus의 관점을 구현한 것이 바로 우리가 여러 번 암묵적으로 접했던 _동형 불변성_의 개념입니다.
우리가 다룬 모든 범주론적 구성(곱/쌍대곱, 시작/종말 대상, 논리에서의 함수 대상)은 _동형 불변_입니다. 또는 동등하게 말해서, 이들은 대상을 동형을 제외하고 정의합니다.
어떤 성질이 동형 불변이라고 불리는 것은, 서로 동형인 둘 이상의 대상이 있을 때 그중 하나가 어떤 성질을 가지면 나머지 대상들도 역시 그 성질을 갖기 때문입니다.
간단히 말해, 범주론에서는 동형 = 같음입니다.
범주론을 이해하는 열쇠는 동형 불변성을 이해하는 데 있습니다. 그리고 동형 불변성을 이해하는 열쇠는 자연 변환입니다.
이전 장의 시작 부분에서 우리가 고민했던 질문으로 돌아가 봅시다. 두 범주가 같다는 것은 무슨 뜻일까요?
이전 장에서는 동형이 얼마나 훌륭한지, 그리고 범주론에서 같음의 개념을 정의하는 데 얼마나 중요한지 많이 이야기했습니다. 하지만 동시에 _범주적 동형_은 범주의 같음 개념을 포착하지 못한다고 말했습니다.
그 이유는 (처음에는 모순처럼 보일지 모르지만) 범주적 동형은 동형 불변이 아니기 때문입니다. 즉, 단지 몇 개의 추가적인 동형 대상이 더 있다는 점만 다른 범주들은 서로 동형이 아닙니다.
이런 이유로 우리는 범주의 같음에 대한 새로운 개념이 필요합니다. 구조가 다른 범주들 사이의 _차이_를 드러내면서도, 범주론적 관점에서 중요하지 않은 차이는 무시한 채 같은 범주론적 구조를 가진 범주들의 _동일성_을 밝혀 주는 개념 말입니다. 그 개념이 바로 _동치_입니다.
Parmenides: 이 범주는 저 다른 범주와 절대로 같을 수 없어 — 대상의 개수가 다르잖아!
Heraclitus: 형, 누가 그런 걸 신경 써, 동형이면 됐지.
동치인 범주를 더 잘 이해하기 위해, 어떤 지도와 그것이 나타내는 지역 사이의 함자 이야기로 돌아가 봅시다(지금은 오직 얇은 범주(AKA preorders)만 고려하겠습니다). 이 함자는 지도가 그 지역을 완전히 표현해야 할 때, 즉 모든 길에 대해 화살표가 있고 모든 작은 장소에 대해 점이 있을 때 가역적일 것이고(따라서 범주들은 동형일 것입니다).
이런 지도는 모든 _장소들_에 대해 알고자 할 때는 필요합니다. 하지만 앞서 말했듯이, 범주론에서 우리는 _장소들_보다 그것들을 연결하는 _경로들_에 더 관심이 있습니다. 즉, 우리는 _대상_보다 _사상_에 초점을 맞춥니다.
예를 들어 교차로들이 어떤 식으로 배치되어 있어서 한쪽에서 다른 쪽으로 가는 경로도 있고 반대로 오는 경로도 있다면, 지도는 그것들을 하나의 교차로로 합쳐 버리더라도 존재하는 모든 경로를 여전히 보여 줄 수 있습니다(세 경로는 “항등 경로”로 표현될 것입니다).
이 두 범주는 동형이 아닙니다 — 한쪽에서 다른 쪽으로 갔다가 다시 돌아오면 같은 대상에 도달하지 않습니다.
하지만 한쪽에서 다른 쪽으로 가면 적어도 _동형인 대상_에는 도달합니다.
이 경우 우리는 그 전순서들이 _동치_라고 말합니다.
두 전순서가 서로 갔다가 다시 돌아오면 같은 대상에 도달하게 하는 두 함자가 있을 때 서로 동형이라는 것은 알고 있습니다.
그리고 두 전순서는 한쪽에서 다른 쪽으로 갔다가 다시 돌아올 때 같은 대상, _혹은 처음 출발한 대상과 동형인 대상_에 도달하면 서로 동치입니다.
그런데 이런 일은 언제 일어날까요? 이를 이해하기 위해 이 전순서들을 Hasse 도표로 그려 봅시다.
모든 대상이 일대일로 연결되는 것은 아니지만, _같은 높이에 있는 모든 대상은 대응되는 높이의 대상들과 연결_되어 있다는 것을 볼 수 있습니다.
이 개념을 형식화하기 위해, 순서에 관한 장에서 다루었던 동치류 개념을 떠올려 봅시다. 위에서 본 두 전순서의 동치류 관계를 시각화해 봅시다.
이들이 서로 동형이라는 것을 볼 수 있습니다. 그리고 이것은 우연이 아닙니다.
두 전순서는, 그들의 동치류들로 이루어진 전순서들이 서로 동형일 때 그리고 그때에만 서로 동치입니다.
이것은 전순서의 동치에 대한 정의이지만, 불행히도 모든 범주에 대해 성립하지는 않습니다. 전순서를 다룰 때는 _대상_만 생각해도 되지만, 범주에서는 사상까지 생각해야 합니다. 즉, 두 범주가 동치임을 보이려면 그들의 사상들 사이의 동형을 세워야 합니다.
예를 들어 다음 두 범주는 그들의 동치류는 서로 동형이지만 동치가 아닙니다. 왼쪽 범주는 사상이 하나뿐이지만, 오른쪽 범주는 둘이기 때문입니다.
범주의 동치를 정의하는 한 가지 방법은 전순서의 동치류 개념을 _뼈대(skeleton)_라고 부르는 것으로 일반화하는 것입니다. 범주의 뼈대란 서로 동형인 모든 대상이 하나의 대상으로 “합쳐진” 부분범주입니다(동형인 대상은 반드시 동일합니다). 즉 전순서의 뼈대는 부분순서입니다.
하지만 이것은(불어를 용서해 주세요) _독자 연습문제_로 남겨 두겠습니다. 왜냐고요? 우리는 집합론적인 일반 함수 개념을 _함자_로 일반화할 때 이미 이런 일을 했고, 따라서 그 개념 위에 쌓아 올리는 것이 더 자연스럽기 때문입니다. 게다가 자연 변환을 도입하기 위한 동기 부여 예시도 필요하잖아요, 기억하시죠?
순서에 관한 장에서 우리는 _대상_에 기초한 순서 _동형_의 정의를 제시했습니다.
순서 동형은 본질적으로 그 순서들의 바탕 집합 사이의 동형(가역 함수)입니다. 하지만 순서는 바탕 집합 외에도 그것들을 연결하는 화살표를 갖고 있으므로, 한 가지 조건이 더 필요합니다. 가역 함수가 순서 동형이 되려면 _그 화살표들을 존중_해야 합니다. 다시 말해 _순서를 보존_해야 합니다. 더 구체적으로는, 한 집합의 임의의 두 원소에 이 함수를 적용했을 때(이를 라고 합시다) 다른 집합에서 같은 대응 순서를 가지는 두 원소가 나와야 합니다(즉 그리고 오직 그럴 때만 ).
이것도 하나의 정의 방식이지만, 가장 좋은 방식은 아닙니다. 이제 우리는 함자에 대해 알고 있고(앞서 말했듯이, 함자는 순서와 다른 범주들 사이의 함수 역할을 합니다), 이를 이용해 새로운 더 간단한 정의를 만들 수 있습니다. 이 정의는 순서뿐 아니라 모든 범주, 그리고 모든 형태의 같음(동형과 동치)에 대해 유효할 것입니다.
우선 집합 동형의 정의부터 시작합시다.
두 집합 와 가 동형(또는 )이라는 것은 함수 와 그 역함수 가 존재해서 와 가 성립하는 경우입니다.
이 정의를 모든 범주에 대해 유효하게 만들기 위해 “function”을 “functor”로, “set”을 “category”로 바꾸기만 하면 됩니다.
두 범주 와 가 동형(또는 )이라는 것은 함자 와 그 역함수 가 존재해서 와 가 성립하는 경우입니다.
Task 1: 이 정의가 타당한지 확인해 보세요.
믿기 어렵겠지만, 이 정의는 단 한 번의 찾아 바꾸기만 하면 _동치_의 정의가 됩니다. 등호를 동형으로 바꾸기만 하면 됩니다(즉, 로).
두 범주 와 가 동치(또는 )라는 것은 함자 와 그 역함수 가 존재해서 와 가 성립하는 경우입니다.
앞서 말했듯, 동형에서는 왔다 갔다 하면 같은 대상에 돌아오지만, 동치에서는 그 대상이 원래 대상과 _동형_이기만 하면 됩니다. 실제로 핵심은 이게 전부입니다.
다만 한 가지 문제가 있습니다 — 함자가 서로 동형이라는 것이 무슨 뜻인지 우리는 아직 말한 적이 없습니다.
그렇다면 위 정의를 어떻게 “살아 움직이게” 만들 수 있을까요? 이 장의 제목이 우리가 정의해야 할 것들을 알려 줍니다.
이게 복잡하게 들린다면, 우리가 늘 하던 일을 하고 있다는 점을 기억하세요 — 동형에 대해 이야기하고 있을 뿐입니다.
이 책의 맨 첫 장에서 우리는 꽤 쉬운 _집합 동형_을 도입했고, 이제는 _함자 동형_을 살펴볼 지점에 도달했습니다. 그러니 같은 일을 하고 있는 셈입니다. 물론 실제로는…
하지만 사실 자연 변환은 사상이나 함자와는 꽤 다릅니다(정의가 함자와 사상처럼 “재귀적”이지 않습니다). 이는 함수와 함자가 모두 대상 사이의 사상(또는 1-사상)인 반면, 자연 변환은 사상 사이의 사상(_2-사상_으로 알려져 있습니다)이기 때문입니다.
하지만 말은 그만하고, 도표를 그려 봅시다. 자연 변환은 함자 사이의 사상이므로, 우선 두 함자를 그려 봅시다.
이 함자들은 같은 시그니처를 가집니다. 당연하죠. 그렇지 않다면 어떻게 그들 사이에 사상이 있을 수 있겠습니까?
이제 함자는 두 개의 사상(대상 사상과 사상 사상)으로 이루어져 있으므로, 함자 사이의 사상은 “대상 사상 사상”과 “사상 사상 사상”으로 이루어질 것입니다(맞아요, 저는 용어 선택 때문에 종종 곤란해집니다. 왜 물으시죠?).
먼저 두 함자의 대상 사상들을 연결해서, 우리가 “대상 사상 사상”이라고 부른 것을 만들어 봅시다.
이름보다 훨씬 간단합니다. 연결해야 할 것은 함자들의 _도착 범주_에 있는 대상들뿐이라는 점을 깨달으면 됩니다. 출발 범주의 대상은 두 함자 모두에서 언제나 같기 때문입니다. 두 함자는 둘 다 출발 범주의 모든 대상을 포함합니다(그게 함자와 일반적인 사상이 하는 일이니까요). 다시 말해, 두 함자의 대상 성분을 연결하는 일은 도착 범주 안에서 몇 개의 사상을 지정하는 것에 지나지 않습니다. 출발 범주의 각 대상마다 하나씩 사상을 지정하면 됩니다. 즉 첫 번째 함자의 상에 있는 각 대상마다 거기서 나오는 화살표가 하나 있어야 합니다(그리고 그것은 두 번째 함자의 어떤 대상으로 가야 합니다). 예를 들어 지금 우리의 출발 범주에는 대상이 둘 있으므로 사상도 둘을 지정합니다.
이 사상은 도착 범주의 모든 대상을 사상하지는 않는다는 점에 주의하세요. 즉 모든 대상에서 화살표가 나오는 것은 아닙니다(예를 들어 여기서는 검은색과 파란색 정사각형에서는 화살표가 나오지 않습니다). 물론 경우에 따라서는 그럴 수도 있습니다.
Task 2: 정확히 언제 이 사상이 모든 대상을 포괄하게 될까요?
사상 부분은 어려워 보일 수 있습니다… 하지만 대상 사상들 사이의 연결이 이미 정해지고 나면, 사상들을 연결하는 방법은 하나뿐이라는 점을 깨닫는 순간 쉬워집니다. 출발 범주의 각 사상에 대해, 두 함자가 도착 범주 안에서 주는 두 사상을 연결하면 됩니다. 그게 전부입니다.
아, 사실 위 도표가 가환해야 한다는 조건도 있습니다(자연성 조건). 하지만 그것은 거의 자동으로 일어납니다.
범주론의 다른 모든 것과 마찬가지로, 자연 변환도 만족해야 할 법칙이 있습니다. 이 경우에는 하나뿐이며, 보통 자연성 법칙 또는 자연성 조건이라고 부릅니다.
이 법칙을 말하기 전에, 우리가 지금 어디까지 왔는지 정리해 봅시다.
와 를 같은 타입 시그니처를 가진 두 함자라고 합시다(즉 어떤 범주 와 에 대해 와 ). 이들 사이의 변환은 도착 범주 안의 사상들의 족(로 표시)을 말하며, 의 각 대상마다 하나씩 있습니다. 이 사상들은 함자의 도착 대상(또는 라고도 부르는, 에서 의 상의 대상) 각각을 의 상의 어떤 대상에 대응시킵니다.
이것은 하나의 _변환_이지만, 반드시 _자연_스러운 것은 아닙니다.
변환이 자연스럽다는 것은, 의 모든 사상이 에 의해 사상들로, 에 의해 사상들로 보내질 때, 가 성립하도록 보내진다는 뜻입니다. 즉 다음 도표가 가환한다는 뜻입니다.
즉 흰색 정사각형에서 시작해서 오른쪽으로 간 뒤 아래로 가는 것(노란색 정사각형을 경유)과, 아래로 간 뒤 오른쪽으로 가는 것(검은색 정사각형을 경유)이 같을 때입니다.
자연 변환은 사상과 가환 정사각형 사이의 사상으로 볼 수 있습니다. 두 범주 사이의 두 함자와 그들 사이의 하나의 자연 변환은, 함자들의 출발 범주에 있는 각 사상마다 도착 범주에 하나의 가환 정사각형이 존재한다는 뜻입니다.
이를 완전히 이해하면, 가환 정사각형도 사상들로 이루어져 있으므로 사상처럼 합성된다는 사실을 알게 됩니다. 적절한 타입 시그니처를 가진 두 사상 와 가 있어 를 만족할 때 세 번째 사상으로 합성할 수 있는 것처럼, 자연성 정사각형도 같은 방식으로 합성됩니다.
이는 자연 변환들이 어떤 …를 이룬다는 뜻입니다.
(아, 잠깐, 그 얘기를 하기엔 아직 이른가요?)
자연 변환이 어떤 범주 안의 사상들의 족이며 일정한 기준을 만족하는 것이라면, 자연 _동형_은 무엇일까요? 맞습니다 — 같은 기준을 만족하는 _동형들_의 족입니다.
도표는 일반적인 자연 변환과 같고, 단지 가 평범한 사상이 아니라 동형이라는 점만 다릅니다.
그리고 이 사상들이 동형이 되면, 도표는 한 가지보다 더 많은 방식으로 가환하게 됩니다. 즉 자연성 조건
i.e. the two paths going from white to blue are equivalent.
이 성립하면, 다음도 성립합니다.
i.e. the two paths going from black to yellow are also equivalent.
죄송한데, 우리가 방금 무슨 이야기를 하고 있었죠? 아, 맞다 — 범주적 동치였죠. 우리가 자연 변환과 동형을 다루는 이유가 범주적 동치 때문이라는 것, 기억하시나요? 아니면 반대였던가요? 뭐 됐습니다. 지금까지 이야기한 내용을 정리해 봅시다.
절의 시작에서 우리는 동치를, 두 함자가 있어서 한쪽에서 다른 쪽으로 갔다가 다시 돌아오면 같은 대상, 혹은 처음 시작한 것과 _동형인 대상_에 이르게 되는 것으로 소개했습니다.
그리고 나서, 얇지 않은(두꺼운?) 범주에서는 상황이 조금 더 복잡하다는 점을 이야기했습니다. 두 대상 사이에 둘 이상의 사상이 있을 수 있기 때문에, 동형인 대상뿐 아니라 _동형인 사상_도 신경 써야 합니다.
이제 우리는 앞서 제시한 정의가 이 두 개념을 어떻게 형식화하는지 보일 것입니다.
두 범주 와 가 동치(또는 )라는 것은 함자 와 그 역함수 가 존재해서 와 가 성립하는 경우입니다.
이 둘이 어떻게 연결되는지 이해하기 위해, 지금까지 예시로 계속 사용한 범주의 항등 함자를 만들어 봅시다. 도표를 더 읽기 쉽게 하기 위해, 각 대상에서 자기 자신으로 화살표 하나만 그리는 대신 같은 범주를 두 번 그린다는 점에 유의하세요.
그다음, 두 범주 사이의 동치를 이루는 두 함자의 합성을 그려 보고, 두 범주가 동형이 아니게 만드는 3개의 “흥미로운” 대상들을 강조해 봅시다.
이제 스스로에게 묻습니다. 이 두 함자 사이에 동형이 존재하는 경우는 언제일까요?
답은 이 세 “흥미로운” 대상을 연결하는 동형 화살표를 다른 방식으로 그려 보면 자명해집니다(기억하세요, 위와 아래는 같은 하나의 범주입니다). 이 화살표들이 바로 두 함자 사이의 동형을 구성하게 해 주는 화살표들입니다(나머지는 그저 항등 화살표일 뿐입니다).
그리고 이 동형이 범주의 구조를 보존하도록 하려면(즉 합성 함자의 출력에 있는 각 사상에 대해 항등 함자의 출력에 대응하는 동등한 사상이 있도록 하려면), 정확히 언제일까요? 바로 그 동형이 _자연_스러울 때입니다. 즉 모든 사상이 가환 정사각형으로 사상될 때입니다. 예를 들어 여기에는 빨간색으로 표시된 사상의 가환 정사각형이 있습니다.
즉 자연성 조건은 함자의 도착 범주에 있는 사상들이 출발 범주의 대응 사상들과 같은 방식으로 행동한다는 것을 보장해 줍니다.
이로써 범주적 동치에 대한 설명은 끝났지만, 자연 변환에 대한 설명은 끝나지 않았습니다 — 자연 변환은 매우 일반적인 개념이고, 범주적 동치는 그중 아주 좁은 경우일 뿐이기 때문입니다.
이 책을 진행하며 우리는 프로그래밍/컴퓨터 과학이 프로그래밍 언어에서의 타입 범주를 연구하는 것이라고 배웠습니다. 하지만(너무 뻔해지는 것을 피하기 위해) 컴퓨터 과학 맥락에서는 표준적인 범주론 개념에 다른 용어를 사용합니다.
대상은 _타입_이라고 하고, 곱과 쌍대곱은 각각 객체/튜플 타입과 합 타입이라고 부릅니다. 그리고 지난 장에서는 함자를 _제네릭 타입_이라고 부른다는 것도 배웠습니다. 이제 이 맥락에서 자연 변환을 무엇이라고 부르는지 배울 차례입니다. 그것은 _(매개변수적) 다형 함수_입니다.
이 말이 조금 막연하게 들린다고 합시다. 프로그래밍에서 자연 변환의 예시가 하나 있으면 좋겠는데… 잠깐, 지난 장에서 뾰족 함자에 대해 이야기할 때 이미 자연 변환을 하나 보여 줬었습니다.
맞습니다. 어떤 함자가 뾰족이라는 것은 그것과 항등 함자 사이에 자연 변환이 있다는 뜻입니다. 즉 각 대상/타입마다 녹색 화살표가 하나씩 있는 것입니다.
그리고 이것은 분명 자연 변환입니다. 사실 자세히 들여다보면, 앞에서 봤던 동치 도표와 꽤 닮아 있다는 것을 알 수 있습니다. 두 변환 모두 항등 함자를 포함하고, 두 변환 모두 같은 범주를 출발점이자 도착점으로 가지기 때문에 모든 것을 하나의 원 안에 넣을 수 있습니다(동치 도표에서는 그렇게 하지 않지만, 그건 단지 표현 방식의 문제일 뿐입니다).
실제로 두 변환의 유일한 차이는, 동치는 어떤 함자들의 항등 함자에 대한 자연 _자연 동형_으로 정의된다는 점( 와 )이고, 뾰족 함자는 항등 함자에서 나가는 한 방향 자연 변환()으로 정의된다는 점입니다. 즉 동치 함자는 뾰족이지만, 그 역은 일반적으로 성립하지 않습니다.
우리는 자연 변환이 프로그래밍에서 (매개변수적) 다형 함수에 해당한다고 말했습니다. 하지만 잠깐, 자연 변환은 원래 다른 것(그리고 훨씬 더 복잡한 것) 아니었나요?
같은 타입 시그니처를 가지는 두 함자 와 (즉 어떤 범주 와 에 대해 와 ), 그리고 의 각 대상마다 하나씩 있는 의 도착 범주 안의 사상들의 족(로 표시). 이 사상들은 의 각 도착 대상(또는 라고도 부르는, 의 상의 대상)을 의 도착 범주의 어떤 대상으로 보낸다.
그렇습니다(혹시 궁금하실까 봐 말하자면, 제가 거짓말한 것은 아닙니다). 다만 프로그래밍의 경우에는 두 함자의 출발 범주와 도착 범주가 모두 같은 범주()이므로, 함자의 타입 시그니처에 관한 조건 전체를 빼 버릴 수 있습니다.
두
functors제네릭 타입 와that have the same type signature그리고 의 각 대상마다 하나씩 있는 안의 사상들의 족(로 표시). 이 사상들은 함자의 각 도착 대상(또는 라고도 부르는 의 상)을 함자 의 어떤 도착 대상으로 보낸다.
지난 장에서 배웠듯이, 프로그래밍에서 함자는 제네릭 타입입니다(적절한 시그니처를 가진 map 함수를 가져야 합니다).
그렇다면 “의 각 대상마다 하나씩 있는 안의 사상들의 족”은 무엇일까요? 이 범주의 사상은 함수이므로, 이는 각 타입마다 하나씩 있는 함수들의 모음일 뿐입니다. Haskell/System F에서는 임의의 타입을 문자 로 표기하면, 그것은 입니다. 그런데 이것이 바로 다형 함수입니다.
좀 더 전통적인 언어로 위 정의를 쓰면 다음과 같습니다(관례에 따라 대신 대문자 <A>를 사용합니다).
function alpha<A>(a: F<A>) : G<A> {
}
제네릭 타입은 <A>를 string, int 같은 구체적인 타입으로 치환하여 작동합니다. 특히 각 값을 길이 1의 리스트에 넣는, 항등 함자에서 리스트 함자로 가는 자연 변환은 이런 모양입니다 . 또는 TypeScript로 쓰면:
function array<A>(a: A) : Array<A> {
return [a]
}
이렇게 과도하게 많은 새로운 용어와 개념이 주는 혼란감에서 벗어나고 나면(그런 데는 몇 년이 걸릴 수도 있습니다), 프로그래머들이 사용하는 다형 함수/자연 변환이 물론 많이 있다는 사실을 깨닫게 됩니다.
예를 들어, 지난 장에서 우리는 모든 값을 길이 1의 리스트에 넣는 함수라는 하나의 자연 변환/다형 함수를 다뤘습니다. 이 함수는 항등 함자와 리스트 함자 사이의 자연 변환입니다.
이 시그니처에서는 유용한 것이 사실상 이것뿐입니다(다른 예로는 등이 있겠지요). 하지만 시그니처에는 리스트를 뒤집는 함수 같은 예시가 많습니다.
…또는 리스트의 첫 번째 원소를 가져오는 take1
또는 리스트들의 리스트를 평범한 리스트로 펴는 _flatten_도 있습니다(이것의 시그니처는 약간 다르며, 입니다).
Task 3: 자연 변환의 자연성 정사각형 예시를 그려 보세요.
나머지 변환들에 대해서도 같은 작업을 해 보세요.
앞에서는 자연성에 대해 너무 걱정할 필요가 없다고 말했습니다. 언제나 만족되기 때문이라고요. 하지만 통계적으로는 그렇지 않습니다 — 제 알기로는 변환의 약 99.999퍼센트는 실제로 자연스럽지 않습니다(그 비율을 정확히 계산할 수 있을지 궁금하네요). 하지만 동시에, 수학에 관해 글을 쓸 때 제가 가장 좋아하는 표현을 빌리자면, 우리가 관심을 갖는 변환들은 공교롭게도 전부 자연스럽습니다.
그렇다면 프로그래밍에서 자연성 조건은 무엇을 의미할까요? 이를 이해하기 위해, 우리가 제시한 변환들의 자연성 정사각형 몇 개를 만들어 봅시다.
우리는 의 역할을 하는 두 타입, 여기서는 와 를 고르고, 항등 함자와 리스트 함자 사이의 변환 같은 자연 변환 하나를 선택합니다.
모든 함수 에 대해, 를 적용하고, 한 함자에 의해 사상된/올려진 버전의 를 적용한 뒤(여기서는 항등 함자이므로 그냥 입니다), 이어서 ()를 적용하는 것이, 먼저 ()를 적용한 다음 다른 함자에 의해 사상된 버전의 를 적용하는 것(여기서는 )과 같을 때 도표는 가환합니다. 즉
(프로그래밍 세계에서는 이것을 같은 식으로도 볼 수 있습니다. 하지만 여기서 function이라는 말은 양쪽에서 서로 다른 것을 뜻한다는 점에 유의하세요. Haskell은 어느 것을 써야 하는지 똑똑하게 추론할 뿐입니다.)
그리고 TypeScript에서, 특히 항등 함자와 리스트 함자에 대해 말하면 이 등식은 다음과 같이 표현됩니다.
[x].map(f) == [f(x)]
그렇다면 우리 경우 이 식은 참일까요? 이를 확인하기 위해 값의 세계를 마지막으로 한 번 더 들여다봅시다.
우리는 을 하나 얻습니다. 즉 리스트가 아닌 단순한 값에 작용하는 함수, 예를 들어 문자열의 문자 수를 반환하는 함수 같은 것을 취한 다음, 리스트 함자(그리고 고차 함수 )를 사용해 더 복잡한 값에 작용하는 함수로 바꿉니다(또는 용어대로 말하면 올립니다).
그다음 이 함수의 입력 타입과 출력 타입(이 경우 와 )과, 이 두 타입에 대응하는 자연 변환의 두 사상(예를 들어 추상 함수 )을 취합니다.
이 두 쌍의 사상을 합성해 보면 실제로 가환한다는 것을 알 수 있습니다 — 결국 실제로는 하나의 동일한 함수인 두 사상을 얻게 됩니다.
위 정사각형은 항등 함자와 리스트 함자 사이의 변환을 보여 줍니다. 이번에는 리스트 함자와 자기 자신 사이의 다른 변환()을 보겠습니다 —
(그리고 이것이 뿐 아니라 어떤 다른 함수에 대해서도 작동한다는 것을 알 수 있습니다.)
그렇다면 왜 이런 일이 일어날까요? 왜 이런 특정한 변환들은 각각의 모든 사상에 대해 가환 정사각형을 만들까요?
답은 적어도 우리의 경우에는 간단합니다. 원래의, 아직 올려지지 않은 함수(우리의 같은 것)는 개별 값에만 작용할 수 있고(구조에는 작용하지 못합니다), 자연 변환 함수, 즉 시그니처를 가진 함수들은 구조만 바꾸고 개별 값은 건드리지 않습니다. 자연성 조건은 바로 이 두 종류의 함수를 어떤 순서로 적용하든 최종 결과가 바뀌지 않는다고 말해 줍니다.
이는 적용하고 싶은 자연 변환들의 열(예: , , 등)과 몇 개의 올려진 함수들(, )이 있을 때, 두 열을 원하는 방식으로 섞어도 같은 결과를 얻는다는 뜻입니다. 예를 들어
은 다음과 같고
…또는…
…또는 다른 어떤 그런 열도 같습니다(허용되지 않는 유일한 것은 두 열의 구성원을 뒤집는 것입니다 — 는 물론 와 다르고, 만약 가 있다면 서로 다른 타입 시그니처 때문에 는 아예 허용되지 않습니다).
Task 4: 자연성 조건 공식을 사용해서 위 결과들을 증명해 보세요.
“부자연스러운” 또는 “비자연적인” 변환(그냥 _변환_이라고 부르겠습니다)은 너무 드물게 언급되기 때문에, 정말 그런 것이 존재하는지 묻게 될지도 모릅니다. 답은 “그렇기도 하고 아니기도 하다”입니다. 왜 그렇다고 할 수 있을까요? 한편으로 변환은 셀 수 없이 많은 사상들로 이루어지고, 그것들이 형성하는 정사각형은 더더욱 셀 수 없이 많습니다. 그리고 그중 일부 정사각형이 가환하지 못하도록 막는 것은 아무것도 없습니다.
예를 들어 자연 변환을 이루는 사상들의 족에서 어떤 하나의 사상을 같은 시그니처를 가진 다른 임의의 사상으로 바꾸면, 그 사상을 구성 요소로 포함하는 모든 정사각형은 더 이상 가환하지 않게 됩니다.
그러면 “거의 자연스러운” 변환 같은 것이 생깁니다(예를 들어, 정수 리스트만 제외하고 모든 리스트를 뒤집는 추상 함수).
그리고 사상이 함수, 즉 값들 사이의 대응인 집합의 범주에서는, 그 값들 중 단 하나의 화살표 하나만 옮겨도 변환은 “비자연적”이 됩니다(예를 들어 하나의 특정 리스트만 제외하고 모든 리스트를 뒤집는 함수).
마지막으로, 조건에 맞는 각 대상마다 하나씩 임의의 사상들을 모아 놓기만 하면, 제가 “완전히 비자연적인 변환”이라고 부르고 싶은 것(물론 이 용어는 제 개인적인 표현입니다)을 얻습니다.
하지만 이런 것들이 존재하더라도, 비자연 변환을 정의하는 것은 매우 어렵습니다. 예를 들어 무한한 범주에 대해서는 무작위성에 의존하지 않고는 이런 “완전히 비자연적인 변환”(즉 어떤 정사각형도 가환하지 않는 것)을 지정할 방법이 없습니다. 그리고 유한 범주에서의 변환이나, 앞서 설명한 “반쯤 자연적인” 변환(하나의 값이나 타입에 대해 하나의 단일 조건을 포함하는 것)조차도 어떤 언어들에서는 표현할 수 없습니다. 예를 들어 Typescript에서는 그런 변환을 정의할 수 있지만, Haskell에서는 할 수 없습니다.
왜 그런지 보려면, 자연 변환의 타입이 무엇인지 봅시다.
핵심은 이 정의가 모든 타입 a에 대해 성립해야 한다는 점입니다. 그래서 타입 다운캐스팅에 의존하지 않고는 타입마다 다른 화살표를 지정할 수 없습니다. 그런데 Haskell 같은 언어에서는 그것이 허용되지 않습니다(매개변수성 원리를 깨기 때문입니다).
위에서 설명한 “반쯤 자연적인” 변환(하나의 값이나 타입에 대한 단일 조건을 포함하는 것), 예를 들어 불리언 리스트만 예외로 하고 모든 리스트를 뒤집는 추상 함수를 정의해 봅시다. Typescript에서는 대략 이렇게 보일 것입니다.
function unnatural<A> (a: Array<A>): Array <A>{
return a
} else {
return a.reverse()
}
}
(이 코드 조각을 보세요! 참 “부자연스럽게” 보이지 않나요?)
이것은 작동하겠지만, 예를 들어 Haskell에서 같은 일을 하려고 하면 즉시 불가능하다고 말할 것입니다(“a is a “rigid type variable” (also known as “Skolem variable” in other context)”). 왜 그럴까요? 기술적인 이유도 있습니다. 이런 런타임 타입 검사는 컴파일 후에도 각 값에 대한 타입 정보를 런타임에 보존해야 하므로 성능 오버헤드를 추가합니다. 하지만 강한 _철학적 이유_도 있습니다. 일반 함수는 일반적인 방식으로 작동해야 한다는 것입니다. 런타임에서 값의 타입을 검사해서 타입마다 다르게 행동하는 함수의 일반성은, 좋게 말해도 의심스럽습니다.
이런 함수는 마치(우리가 Curry-Howard 동형의 논리 쪽으로 전환한다면) “모든 는 어떤 성질을 가진다”라는 일반 명제를, 현재 존재하는 들이 우연히 그 성질을 가진다는 사실만으로 증명하는 것과 같습니다. 어떤 맥락에서는 유효할 수 있더라도, 그런 증명은 범위와 정보량 모두에서 매우 제한적입니다. 예를 들어 옆 테이블에 앉은 사람들이 모두 갈색 머리를 가졌다고 해도, 그것이 참인 더 깊은 이유가 없다면 실질적인 의미는 거의 없습니다.
다시 말해, 비자연 변환이 Haskell에서 작동하지 않는 이유는 그것들이 정말로 … 부자연스럽기 때문입니다. 즉 법칙을 따르지 않기 때문입니다.
참고로, 프로그래밍에서는 이 원리를 “parametricity”라고 부르고, 자연스러운 추상 함수들을 “parametrically polymorphic”라고 부릅니다. 반면 비자연적인 다형 함수는 ad-hoc polymorphic으로 알려져 있습니다.
이제 자연 변환의 정의를 보았으니, 이제는 자연 변환의 정의를 볼 시간입니다(그리고 이 책의 유머 수준이 점점 떨어지고 있다고 느끼신다면, 그건 단지 이제 일이 진지해지고 있기 때문입니다).
자연 변환을 나타내는 가환 도표를 다시 한 번 살펴봅시다.
이 도표는 자연 변환을, 각 사상에서 하나가 아니라 두 개의 화살표가 나오는 어떤 “두 화살표 함자”처럼 보게 만들 수 있습니다. 이 개념은 _곱 범주_를 사용하여 형식화할 수 있습니다.
아 잠깐, 곱 범주를 아직 다루지 않았군요… 하지만 걱정 마세요. 지금 다룰 겁니다.
우리는 곱 범주를 다루지 않았습니다. 하지만 몇 장 전에 모노이드와 군을 다룰 때 곱군 개념을 이야기했습니다. 좋은 소식은 곱 _범주_가 곱 _군_의 일반화라는 점입니다…
나쁜 소식은 아마 곱군에 대해 거의 기억하지 못하실 거라는 점입니다. 짧게 다뤘으니까요.
하지만 걱정 마세요. 지금 더 자세히 다뤄 보겠습니다.
원소들의 집합을 각각 와 로도 표기할 수 있는 두 군 와 가 주어졌을 때…
(이 예에서는 두 개의 불리언 군을 사용하며, 정사각형의 가로 회전과 세로 회전의 군으로 시각화합니다)
…이 두 군의 _곱군_은 이 두 집합의 데카르트 곱을 원소 집합으로 갖는 군입니다.
그렇다면 그런 군의 군 연산은 무엇일까요? 음, 이 집합 위에 존재할 수 있는 몇 안 되는 군 연산들 가운데, 이것이 자연스러운 유일한 연산이라고 저는 말하고 싶습니다(이 절에 자연 변환을 끌어들일 생각은 없었지만, 정말 어디에나 나타나는군요). 그럼 이 군의 연산을 도출해 봅시다.
군 연산이 원칙적으로 무엇인지는 알고 있습니다. 군 연산은 군의 두 원소를 세 번째 원소로 결합합니다. 즉 다음과 같은 타입 시그니처를 가진 함수입니다.
또는 동등하게
그리고 곱군의 경우, 군의 바탕 집합(위에서 라고 부른 것)은 다른 두 집합 와 의 데카르트 곱이라고 했습니다. 따라서 를 로 바꾸면 정의는 다음이 됩니다.
즉 군 연산은 와 의 원소 한 쌍과 또 다른 한 쌍을 받아서, 예상하셨겠지만, 와 의 원소 한 쌍을 돌려줍니다.
예를 들어 봅시다. 혼동을 피하기 위해 완전히 다른 두 군, 색 혼합 군과 덧셈에 대한 정수의 군을 택합시다. 그러면 의 값은 임의의 색과 임의의 숫자를 담은 쌍이 되고, 연산은 그런 두 쌍을 결합해서 또 다른 쌍을 만들어야 합니다.
이 연산은 숫자와 색을 담은 쌍을 내놓아야 합니다. 더 나아가, 두 숫자로부터 그 두 숫자를 사용해서 숫자를 만들고, 색도 마찬가지로 하는 것이 좋습니다. 게다가 우리는 이것이 숫자와 색의 모노이드뿐 아니라 우리에게 주어질 수 있는 모든 다른 모노이드에 대해서도 작동하길 원합니다. 그러니 새 쌍의 원소를 주어진 두 쌍의 각 원소들을 결합해서 얻는 것 외에 다른 해법이 없다는 것은 자명합니다.
그리고 앞서 제시한 두 불리언 군의 곱군의 연산은, 두 연산을 결합한 것입니다.
따라서 연산의 일반 정의는 다음과 같습니다(, 는 의 원소이고 와 는 의 원소입니다).
그리고 이것이 곱군입니다.
이제 다시 곱 _범주_를 다루러 돌아왔습니다.
우리는 곱 _군_이 무엇인지 알고 있고, 군은 대상이 하나뿐인 범주에 지나지 않는다는 것도 알고 있습니다(군의 원소들이 그 범주의 사상이라는 것, 기억하시죠?). 그러니 거의 다 온 셈입니다.
곱범주를 만드는 한 가지 방법은 이렇습니다.
아무 두 범주나 잡습니다.
그다음 이 범주들의 대상들로 만들 수 있는 모든 가능한 쌍들의 집합을 취합니다.
그리고 마지막으로, 두 범주 중 어느 하나에서 오는 모든 사상을 취해 그 타입 시그니처에 등장하는 어떤 대상이 포함된 모든 쌍들에 대해 그것들을 복제함으로써(곱군에서 했던 것과 같은 방식으로) 이 집합으로 범주를 만듭니다. 이 예에서는 두 범주 중 하나만 사상을 가집니다.
이것이 두 범주의 _곱범주_입니다.
두 범주 와 의 곱범주, 기호로 는, 와 의 바탕 집합의 곱집합을 바탕 집합으로 가지는 범주입니다. 그리고 그 사상은 와 의 사상들을 결합한 것으로, 쌍의 한 요소를 바꾸도록 변형됩니다. 즉 의 각 사상 에 대해 에 사상 이 있고, 마찬가지로 의 각 사상에 대해서도 그렇습니다.
이 절에서 우리가 관심을 갖는 것은 하나의 특별한 범주의 곱입니다. 바로 대상이 둘이고 사상이 하나인, 우리가 라고 부르던 범주입니다(세련되게 흑백으로 표현됩니다).
이 범주는 자연 변환과 동등한 함자를 구성하는 열쇠입니다.
따라서 와 어떤 다른 범주의 곱범주가 주어지면…
…와 곱범주 사이에 자연 변환이 존재합니다.
게다가 이 연결은 양방향입니다.
범주 에서 다른 범주 로 가는 임의의 자연 변환은 하나의 함자 로 나타낼 수 있으며, 그 역도 성립합니다.
즉 자연 변환 이 있다면(여기서 와 ), 또한 함자 가 존재해서, 에서 쌍의 일부로 대상 를 갖는 대상들과 그들 사이의 사상들만으로 이루어진 부분범주를 취하면 와 동등한 함자를 얻고, 를 포함하는 부분범주를 취하면 그 함자는 와 동등해집니다(이를 와 로 씁니다). Voilà!
Task 5: 두 정의가 동등함을 보여 보세요.
이 관점은 자연 변환을 가환 정사각형들의 모음으로 볼 수 있게 해 줍니다. 출발 함자는 각 정사각형의 왼쪽 변을, 도착 함자는 오른쪽 변을 정의하고, 변환의 사상들은 이 두 변을 이어 줍니다.
우리는 이 함자들의 출발 범주의 구조까지도 다시 얻어낼 수 있으며, 범주는 정의상 구조 그 자체이므로, 이는 범주 자체를 복원하는 것과 같습니다.
이제 아주 특이한 막간으로 들어가서, 곱군의 군 연산이 사실 자연 변환이라는 것을 보이겠습니다.
왜 그런지 이해하려면, 방정식들을 다시 한 번 봅시다.
우리는 이 방정식들의 해가 의미 있으려면, 숫자와 색뿐 아니라 모든 모노이드에 대해 작동해야 한다고 말했습니다. 다시 말해, 두 모노이드를 받아 세 번째 모노이드를 만들어 내는 메커니즘이 있어야 합니다. 이 메커니즘은 다름 아닌 다형 함수일 수밖에 없습니다.
위에서 우리는 다형 함수가 변환이라는 것을 보였습니다(이 경우는 하나가 아니라 두 타입에 대해 매개변수화되어 있으므로 조금 더 생각하기 어렵지만, 2장에서 두 인자를 받는 함수를 한 인자를 받는 함수로 표현하는 법을 배웠습니다).
그리고 자연성 조건은 우리의 해법이 숫자/색 등을 주어진 두 숫자/색을 사용해서 만들어 내게 보장해 줍니다. 무작위로 하나를 고르는 것이 아니라요.
곱군의 모든 경우에 대해 자연성 조건이 실제로 성립한다는 것(구성상 올바르다는 것)을 증명할 수 있습니다.
자연 변환은 확실히 평범한 사상이나 함자와는 다른 종류의 존재이므로, 같은 방식으로 합성되지는 않습니다. 하지만 분명 합성되며, 여기서 그 방법을 보이겠습니다.
먼저 자명한 정의 하나를 치워 두겠습니다.
각 함자마다, 자기 자신과 자기 자신 사이의 항등 자연 변환(사실 자연 동형)이 존재합니다.
자연 변환을 합성하기 위한 설정은 처음 보면 복잡해 보일 수 있습니다. 세 범주 , , 가 필요합니다(사상의 합성이 세 대상을 요구하는 것과 마찬가지입니다). 또한 총 네 개의 함자가 필요하며, 두 쌍으로 나뉩니다. 한 쌍은 에서 로 가고, 다른 쌍은 에서 로 갑니다(그래야 이 두 쌍의 함자를 다시 합성해서 로 가는 새로운 한 쌍의 함자를 얻을 수 있습니다). 하지만 최대한 단순하게 하기 위해, 자연 변환을 사상에서 가환 정사각형으로 가는 사상으로 보겠습니다. 위에서 보았듯이, 이 사상은 이미 그 안에 두 함자를 포함하고 있습니다.
따라서, 함자 들이 관여하는 자연 변환이 있다고 합시다(우리는 보통 이를 와 라고 부릅니다).
그렇다면 로 가는 함자들(라벨은 와 )이 관여하는 변환이 하나 더 있다면 무슨 일이 일어날까요? 자연 변환은 각 사상을 하나의 정사각형에 대응시키고, 정사각형은 네 개의 사상(두 함자에 의한 두 투영과 변환의 두 성분)을 포함하므로, 하나의 정사각형은 네 개의 정사각형으로 사상될 것입니다.
우선 의 사상의 각 투영에 대해 둘씩 그려 봅시다.
자연 변환의 성분인 두 사상에 해당하는 정사각형도 둘 더 있어야 합니다. 하지만 이 사상들은 이미 도표 위에 있는, 두 함자의 도착 대상들을 연결하므로, 우리는 그들 사이의 연결만 그려 주면 됩니다.
그 결과는 때때로 정육면체로 시각화되는 흥미로운 구조가 됩니다.
더 흥미롭게도, 정육면체의 옆면에 있는 가환 정사각형들을 수평으로 합성하면, 그 안에 하나가 아니라 두 개의 더 큰 가환 정사각형(이 도표에서는 _직사각형_처럼 보입니다)이 있다는 것을 알 수 있습니다. 회색과 빨간색으로 표시된 그것들은 모두 사상 와 를 연결합니다.
따라서 합성 함자 와 사이에 자연 변환이 존재합니다 — 보통 (검은 점으로) 표시하는 자연 변환입니다.
Task 6: 자연 변환이 실제로 합성된다는 것을 보이세요. 즉 자연 변환 와 가 있으면 가 성립함을 보이세요.
수평 합성의 흥미로운 특수한 경우는 항등 자연 변환이 포함된 수평 합성입니다. 시그니처 가 있는 함자들이 관여하는 자연 변환 과, 시그니처 가 있는 어떤 함자 가 주어졌다고 합시다. 이때 를 함자 와 자기 자신 사이의 항등 자연 변환으로 두고, 그것을 와 합성할 수 있습니다.
그러면 새로운 자연 변환 를 얻게 되는데, 이것은 사실상 우리가 시작한 것(즉 )과 거의 같습니다. 그러면 무슨 의미가 있을까요? 우리는 함자를 사용해 자연 변환을 _확장_하는 방법을 찾은 것입니다. 즉 시그니처 를 가진 함자를 사용해 자연 변환 을 확장하여 로 만들 수 있습니다.
Task 7: 이번에는 를 항등으로 두고, 자연 변환을 반대 방향으로 확장해 보세요.
이것이 자연 변환을 합성하는 방식입니다. 아쉽게도 이 합성은 표준적인 범주적 합성과는 다릅니다. 그렇다면 우리가 기대했던 것처럼 자연 변환은 범주를 이루지 못하겠군요…
음, 사실 범주를 합성하는 또 다른 방식이 하나 있고, 그것은 실제로 될지도 모릅니다.
범주적 합성은 세 대상과 그 사이의 연속된 두 화살표를 필요로 한다는 것을 떠올려 봅시다. 자연 변환의 수직 합성을 위해서는, 같은 타입 시그니처를 가진 세 개(또는 그 이상)의 함자, 예를 들어 즉 (같은 출발 범주와 도착 범주)를 가진 것들과, 그 함자들 사이의 연속된 두 자연 변환 즉 와 가 필요합니다.
자연 변환 의 각 사상(예를 들어 )과 자연 변환 의 대응하는 사상(예를 들어 )을 결합해서 새로운 사상 하나를 얻을 수 있습니다. 이를 라고 부르겠습니다(합성 연산자는 보통의 흰 원이며, 수평 합성을 나타내는 검은 원과 구별됩니다). 그리고 이런 모든 사상들의 집합은 정확히 새로운 자연 변환 의 성분들이 됩니다.
세 개의 함자 와, 그들 사이의 연속된 두 자연 변환 즉 와 가 주어지면, 자연 변환 가 존재하며, 그 성분은 자연 변환 의 각 사상(예: )과 자연 변환 의 대응하는 사상(예: )의 합성입니다.
이제 장의 끝에 가까워졌으니, 우리의 범주를 도입하고 마무리하겠습니다. 그러기 위해 먼저 자연 변환의 수직 합성에 대한 좀 더 압축된 표기법을 도입합니다(여기서는 정말 수직으로 보입니다).
우리는 이 장을 시작하면서 집합의 범주를 보았고, 집합의 원소를 점으로, 집합/대상을 그 원소들의 모임으로 나타내는 내부 도표를 사용했습니다.
Task 8: 이 도표에서 사용된 함수, 세 함자, 두 자연 변환이 무엇인지 찾아보세요.
그다음 우리는 곧바로 외부 도표로 넘어갔습니다. 거기서는 대상이 점이고 범주가 모임입니다.
그리고 이제 한 단계 더 나아가 범주의 범주를 봅니다. 여기서는 범주가 점이고 함자가 사상입니다.
이 표기에서는 자연 변환을 사상들 사이의 (이중) 화살표로 나타냅니다.
그리고 이제 형성되는 새로운 범주를 볼 수 있습니다.
임의의 두 범주 와 에 대해, 함자를 대상으로 하고 그 함자들 사이의 자연 변환을 사상으로 하는 범주 가 존재합니다.
자연 변환은 수직 합성으로 합성되며, 물론 항등 자연 변환은 항등 사상입니다.
자연 변환의 수직 합성과 수평 합성은 다음과 같은 방식으로 서로 관련됩니다.
우리가 (그랬던 것처럼) 수직 의미에서 연속된 두 자연 변환, 예를 들어 와 를 가지고 있고,
또 이번에는 수평 의미에서 연속된 두 자연 변환, 예를 들어 와 도 있다고 합시다. (여기서 는 와 아무 관계가 없고, 도 와 아무 관계가 없습니다. 단지 글자를 너무 많이 쓰지 않으려고 그렇게 부를 뿐입니다.)
그리고 두 쌍의 자연 변환이 모두 같은 범주와 같은 함자에서 시작한다면, 이 두 쌍의 자연 변환의 합성은 다음 법칙을 만족합니다.
Task 9: 변환들의 두 합성(식의 양변)의 경로를 그려 보고, 그것들이 실제로 같은 곳으로 간다는 것을 확인해 보세요.
이쯤 되면 여러분은 이런 생각을 할지도 모릅니다(물론 통계적으로는 “이게 대체 다 무슨 소리야?”라고 생각하실 가능성이 더 높겠지만요). 모든 범주는 작은 범주의 범주 의 대상이고, 그 안에서 함자는 사상 역할을 합니다.
그런데 주어진 범주들 사이의 함자들 역시 수직 합성 아래에서 하나의 범주를 이룹니다. 이는 가 (다른 모든 범주처럼) 대상 사이의 사상뿐 아니라, _사상 사이의 사상_도 가진다는 뜻입니다. 그리고 더 나아가, 이 두 종류의 사상은 매우 흥미로운 방식으로 합성됩니다.
그렇다면 는 무엇이 되는 걸까요? 자연 변환을 “2-사상”이라고 부를 수도 있겠고, 는 어떤 종류의 “2-범주”라고 할 수 있지 않을까요?
하지만 잠깐, 사실 여러분이 그걸 알기에는 아직 너무 이릅니다. 우리는 아직 한계도 다루지 않았는걸요…
Task 1: 이 정의가 타당한지 확인해 보세요.
문제가 되는 정의는 다음입니다.
두 범주 와 가 동형(또는 )이라는 것은 함자 와 그 역함수 가 존재해서 와 가 성립하는 경우입니다.
우리는 함자의 정의를 펼쳐 봄으로써 이를 확인할 수 있습니다.
함자는 다음으로 이루어집니다.
대상 사상을 펼치면 정확히 집합 동형의 정의가 나옵니다.
두 집합 와 가 동형(또는 )이라는 것은 함수 와 그 역함수 가 존재해서 와 가 성립하는 경우입니다.
사상 사상과 법칙을 펼치면 나머지가 나옵니다.
Task 2: 정확히 언제 이 사상이 모든 대상을 포괄하게 될까요?
위에서 말했듯이:
두 함자의 대상 성분을 사상하는 일은 도착 범주 안의 몇 개의 사상을 지정하는 것에 지나지 않습니다. 출발 범주의 각 대상마다 하나씩 사상을 지정하면 됩니다. 즉 첫 번째 함자의 상에 있는 각 대상마다 거기서 나오는 화살표가 하나 있어야 합니다.
따라서 이 사상은 함자의 상에 있는 모든 대상을 포괄합니다. 그렇다면 이것이 아예 모든 대상을 포괄하게 되는 때는 언제일까요? 간단합니다 — 함자가 일대일일 때입니다(또는 대상마다 화살표가 둘 이상 있어도 괜찮다면 전사일 때). 아마도 이는 두 범주가 실제로 하나의 같은 범주이고, 그 함자가 항등 함자일 때일 가능성이 큽니다.
Task 3: 자연 변환의 자연성 정사각형 예시를 그려 보세요.
자연 변환의 정사각형을 그리려면 먼저 다음을 해야 합니다.
그다음 우리는:
올바르게 했다면 정사각형은 가환할 것입니다.
Task 4: 자연성 조건의 공식을 사용해 위 결과들을 증명해 보세요.
우리가 증명하고 싶은 것은 다음입니다.
이것이 다음과 같다는 것입니다.
식의 일부에는 “올려진” 함수(함자의 적용 결과인 함수)와 그 뒤의 자연 변환이 들어 있습니다.
자연성은 다음을 말합니다.
이제 를 로 바꾸고( 가 자연 변환이므로), 와 둘 다 로 바꿀 수 있습니다( 와 가 같은 함자, 즉 리스트이므로).
이를 적용하면 다음을 얻습니다.
Task 5: [자연 변환의] 두 정의가 동등함을 보여 보세요.
이는 함자 로부터 자연 변환을 추출하는 것과, 그 반대 방향을 포함합니다.
여기서는 이 과정의 한 방향을 설명하겠습니다.
앞서 말했듯이, 범주 를 두 부분범주(이를 와 라고 합시다)로 나눌 수 있으며, 둘 다 와 동형입니다. 하나는 의 첫 번째 대상과 짝지어진 대상들을 포함하고, 다른 하나는 두 번째 대상과 짝지어진 대상들을 포함합니다.
마찬가지로 함자도 두 함자 와 로 나눌 수 있습니다.
이제 해야 할 일은 두 함자 사이에 범주 안의 사상들의 족이 존재한다는 것, 즉 자연 변환이 존재한다는 것을 보이는 것입니다. 이 사상들은 두 함자의 상을 연결해야 합니다.
이 족은 범주 의 사상들의 상입니다. 즉 를 훑으면서 범주에서 오는 모든 사상을 모으면, 이미 우리의 변환을 얻은 것입니다.
이 변환이 자연스러운 이유는 곱범주의 합성이 정의되는 방식 때문입니다(곱을 이루는 범주들의 사상들의 성분별 합성으로 정의됩니다).
Task 6: 자연 변환이 실제로 합성된다는 것을 보이세요. 즉 자연 변환 와 가 있으면 가 성립함을 보이세요.
두 변환이 합성된다는 것을 보이려면, 위 시그니처를 가진 두 자연 변환이 주어졌을 때 새로운 하나를 구성하는 방법을 찾으면 됩니다.
이를 위해 자연 변환이란 범주의 각 대상마다 하나씩 있는 사상들의 족일 뿐이라는 점, 그리고 우리가 사상들을 합성할 줄 안다는 점을 떠올립니다.
의 각 대상 에 대해, 자연 변환 에서 그것에 대응하는 사상을 라 하고, 에서 대응하는 사상을 라 합시다.
그렇다면 에서 그것에 대응하는 사상은, 정육면체의 회색 화살표를 따라가면 이고, 또는 다른 쪽 회색 화살표를 따라가면 입니다. 혹은 표기에 그다지 신경 쓰지 않는다면 그냥 이라고 해도 됩니다.
그런 사상들이 하나의 변환을 이룬다는 것은 그 사상들의 시그니처에서 따라옵니다.
이 변환이 자연스럽다는 것은, 모든 그런 사상에 대해 가환 정사각형이 있기 때문입니다.
Task 7: 이번에는 를 항등으로 두고, 자연 변환을 반대 방향으로 확장해 보세요.
기본적으로 똑같은 방식으로 작동하며, 결과도 같습니다 — 단지 시그니처가 다른 새로운 자연 변환을 얻게 됩니다.
Task 8: 이 도표에서 사용된 함수, 세 함자, 두 자연 변환이 무엇인지 찾아보세요.
먼저 함자들: 와 는 함자이고, 는 함자입니다.
자연 변환: 는 이고, 는 입니다(좀 더 엄밀히 말하자면, 이 경우 타입은 Non-empty list여야 합니다. 왜냐하면 는 의 부분 자연 변환일 뿐이기 때문입니다).
함수는 늘 그렇듯 입니다.
Task 9: 변환들의 두 합성(식의 양변)의 경로를 그려 보고, 그것들이 실제로 같은 곳으로 간다는 것을 확인해 보세요.
한 가지 방법은 다음과 같습니다.