실제 Functor는 무엇을 의미하는가?

Functor

카테고리 사이에서의 사상(morphisms)

  • 동질의 대상들을 규정하면, 그 사이를 비교하거나 대응하기 위한 수단도 필요하다.
  • 집합의 경우 집합 사이의 함수가 그것이다.
  • 그래서 대상들 사이에는 사상(morphisms)가 있을 수 밖에 없다.
  • 카테고리 이론는 그 대상들 사이의 사상을 가지는 체계 자체를 다시 대상으로 하는 메타수학 이론이다.
  • 이렇게 해서 그러한 구조를 가진 체계들의 일반적인 원리를 도출하는 것을 목적으로 한다.

카테고리 이론에서는 왼쪽의 집합/함수의 체계 자체를 오른쪽 처럼 규정하고, 이를 “대상”으로 다룬다.

정의

다음을 보존하며 한 카테고리의 대상과 사상을, 다른 카테고리의 대상과 사상에 각각 대응시키는 관계

  1. 대상과 사상의 구조를 보존한다.
  2. 항등 사상을 보존한다.
    • f가 항등사상일 경우 변환했을 때 F(f)도 항등 사상이어야 한다.
  3. 사상의 합성관계를 보존한다.
    • C에 라 할경우, 가 되어야 한다.

함자는 사상인가?

  • 함자는 대상이 카테고리일 뿐, 사상임은 동일하다.
  • 그리고 함자는 합성 가능하다.
  • 항등 변환도 있다. 카테고리를 자신으로 설정만 하면 된다.
  • 결국 함자는 완벽히 사상의 조건을 만족한다.
  • 이는 곧 이전 장에서 알아본 사상의 특징들은 함자에 모두 적용된다.
  • 함자도 Isomorphism(동형 사상)이거나 monomorphism일 수 있다는 것이다.
  • 특히 Isomorphism에 해당하는 함자들이 이론적으로 중요하다.
    • 역사상이 존재하는 함자를 말함

Endofunctor

  • 프로그래머에게 가장 중요한 함자는 정의역과 공역이 같은, 즉, C에서 C로 가는 것들이다.
  • 프로그래밍의 Functor는 바로 타입(Type) 카테고리의 자기 함자를 의미한다.
  • 여기서 Type은 프로그래밍에서 사용하는 Type을 의미한다.
  • T-> F<T>, U -> F<U>, f -> lift(f)의 형태로 변환 되는 것이다.

프로그래밍에 사용되는 다른 함자

  • 그렇지만 모든 프로그래밍에서 사용되는 모든 함자가 자기 함자인 것은 아니다.

Evaluator

Evaluator<T>: T -> Double

  • 위와 같은 형태의 01. Type Constructor (Generic function)를 생각해보자.
  • endo functor인지 확인해보자.
  • 임의의 T타입을 Evaluator<T>로 만들 수 있는가? : O
  • 임의의 U타입을 Evaluator<U>로 만들 수 있는가? : O
  • lift함수를 정의할 수 있는가?: X
func lift<T, U>(_ f: @escaping T -> U) -> (Evaluator<T> -> Evaluator<U>) {
	{  et in
		// ???		
	}
}
 
func lift<T, U>(_ f: @escaping T -> U) -> (T? -> U?) {
	{  op in
		switch op {
		case .some(let p):
			return .some(f(p))
		case .none:
			return .none
		}
	}
}
  • 이렇게 정의가 불가능하다.
  • 그런데 이렇게 하면 정의가 가능하다.
func antiLift<T, U>(_ f: @escaping U -> T) -> (Evaluator<T> -> Evaluator<U>) {
	{  et in
		et.transform(f) // T 변수에 접근하여 값을 U로 변환하는 것을 표현함
	}
}
  • `f: U -> T
  • et: T -> Double
  • et o f: U -> Double == Evaluator<U>
  • 이와 같이 주어지는 함수에 따라 lift가 가능한 경우도 있다.
  • 이는 완전히 “타입 카테고리의 자기함자”는 아니지만, 다른 의미가 있다.
  • Evaluator는 Type의 Opposite Category이다. (Type_op => Type Functor)

Opposite Category

  • Type_op(Type opposite): Type에서 사상의 방향만 반대로 한 카테고리
  • 카테고리가 되기 위한 조건은 항등 사상 존재, 합성 가능밖에 없다.
  • 그렇기 때문에 Type Opposite은 카테고리의 조건을 만족한다.
  • Opposite Category에서는 U->T 함수가 T->U로 가는 사상으로 취급된다.

contravariant functor

  • Evaluator는 이와 같이 정리할 수 있다.
  • 이런 식으로 C_op -> D으로 가는 함자를 C -> D로 가는 contravariant 함자, 반변 함자라고 한다.
  • 즉, Evaluator는 Type에 대한 Covariant endofunctor이다.
    • Opposite Type Category에서 Type Category로 가는 함자

Pair

Pair<T, U>: T, U를 주면 Tuple을 만들어줌

func lift<U, V>(_ f: @escaping U -> V) -> (Pair<T, U> -> Pair<T, V>) {
	{ pairTU in
		(pairTU.first, f(pairTU.second))
	}
}
 
func lift<U, V>(_ f: @escaping U -> V) -> (Pair<U, T> -> Pair<V, T>) {
	{ pairUT in
		(f(pairUT.first), pairUT.second)
	}
}
  • TU가 하나씩 고정된 상황에서 lift 함수를 정의하는 것은 간단하다.
    • 이는 곧 Pair가 자기 함자임을 나타내는 것과 동치이다.
    • U -> Pair<T, U>, V -> Pair<T, V>로 만드는 건 당연하니 사상에 대한 변환만 확인하면 된다.
  • 그럼 Pair 자체는 어떨까?

Product Category

  • 순서쌍을 대상으로 하는 카테고리를 정의해보자.
  • C, D 카테고리가 있을 때, 각각에 대응되는 대상을 순서쌍으로 만들 수 있을 것이다.
  • 이렇게 대상의 순서쌍을 다시 대상으로, 사상의 순서쌍을 다시 사상으로 하는 카테고리를 Product 카테고리라 한다.

  • PairType x Type에서 Type으로 가는 함자이다.
  • f: X1 -> Y1, g: X2 -> Y2 함수의 순서쌍이 주어지면, Pair<X1, X2> -> Pair<Y1, Y2>의 함수도 쉽게 만들 수 있다.

두개의 타입 인수를 가진 Type Constructor

일반적으로 두개의 타입인 수를 가진 01. Type Constructor는, 다음을 만족할 경우 항상 Type x Type -> Type 함자가 된다.

  1. F<T, >Type -> Type Functor이다.
  2. F<, T>Type -> Type Functor이다.

이런 경우는 어떨까?

두개의 인자를 갖는 Functor F는 아래를 만족한다.

  1. F<T, >Type_op -> Type Functor이다.
  2. F<, T>Type -> Type Functor이다.

단순하다. F는 Type_op x Type -> Type 함자가 된다. 함수 타입Function<T, U> == T -> U을 만드는 01. Type Constructor가 대표적이다.

어어.. 여기서 머리가 안돌아가는데 걱정말자.

정리

  • 위에서 알아본 Functor는 프로그래밍에서의 Functor에 포함되지는 않는다.
  • 프로그래밍에서의 Functor는 Type -> Type, 즉 자기 함자에서 그치기 때문이다.
  • 수학에서의 Functor는 많은 것을 포함하는 일반적인 개념이다.
  • 적당히 이해했다면 넘어가도 무방하다.

Reference