DEV Community

loading...
Cover image for Applicative Functor의 수학적 이해

Applicative Functor의 수학적 이해

ingun37 profile image Ingun 전인건 ・2 min read

아래는 제가 생각했을때 가장 좋은 Applicative 를 설명하는 방법이에요.

이 글의 목적은 수학을 잘 모르더라도 Applicative Functor 의 수학적 배경을 이해할 수 있게끔 쉽게 설명하는것이 목적이에요.

모든건 매우 단순한 수학적 구조 중 하나인 Apply 로 부터 시작해요.

Apply 란?

생소해서 뭔지 모르겠다고 생각하실 수도 있지만 절대 그렇지 않아요. 프로그래머라면 이미 Apply 마스터에요. Apply 는 2항 함수에요. 어떤 함수 f:XY f:X \rightarrow Y xX x \in X 를 받아서 x x f f 에 적용한 결과값을 리턴해요.

apply:YX×XYapply(f,x)=f(x) \begin{aligned} &\text{apply}:Y^X \times X \rightarrow Y \newline \\ &\text{apply}(f,x) = f(x) \end{aligned}

쉽게 말해서 우리가 프로그래밍과 수학에서 늘 쓰던 notation 인 f(x) 의 이름이에요. 대부분은 아마 apply 를 너무 당연한듯이 써와서 이름을 알 필요성도 못느꼈을거에요.

하찮아 보일 수도 있지만 apply 도 법칙이 있어요. 이름하야 Applicative rule 이죠.

Rule 1 - identity

apply(id,x) \text{apply}(\text{id},x) 는 언제나 x x 를 그대로 리턴해야 해요. 여기서 id 는 파라메터로 받은 x 를 그대로 리턴하는 함수에요.

Alt Text

Rule 2 - composition

다음이 성립해야 해요.

apply(f,apply(g,x))=apply(apply(apply(,f),g),x) \text{apply}(f, \text{apply}(g,x)) = \text{apply}( \text{apply}(\text{apply}( \cdot , f), g),x)

Alt Text

참고로 apply(,f)\text{apply}( \cdot , f) 는 합성 함수 f(g)=fg \cdot_f(g) = f \cdot g 의 curried 된 형태가 되어요.

위 매우 단순해보이는 법칙들이 수학과 프로그래밍이 고장나지 않게끔 유지해준답니다.

Applicative Functor란?

수학적 구조를 보존한다는 컨셉은 수학의 근본중 하나이고, 모든곳에서 나타나요. 예를들어 행렬은 선형성을, homomorphism 은 대수적 구조를, 연속함수는 위상구조를, Functor 는 Categorical 구조를 보존해주죠.

Applicative Functor는 Categorical 구조와 더불어 Applicative rules 를 보존해주어요. 다른말로, Applicative functor는 universal constructor와, ( η\eta 라고 부를게요)

η:XAX \eta:X \rightarrow AX

Functor A 로 lift 된 타입들을 위한 apply 인 applyA:A(X>Y)>AZ \text{apply}_A : A(X -> Y) -> AZ 을 제공해 주고,

합성 가능한 두 함수 f f g g 그리고 g 의 도메인에 속한 x x 가 주어졌을때, 이들이 η \eta 로 transform 되었을때 Applicative rule 이 보존 된다는 뜻이에요.

applyA(Aid,Ax)=Ax \text{apply}_A ( A\text{id}, A x) = A x

Alt Text

applyA(Af,applyA(Ag,Ax))=applyA(applyA(applyA(A,Af),Ag),Ax) \text{apply}_A(Af, \text{apply}_A(Ag,Ax)) = \text{apply}_A( \text{apply}_A(\text{apply}_A( A, Af), Ag),Ax)

Alt Text

다시 말하지만, 수학적 구조를 보존하는것이 핵심이에요.

참고로 η\eta 는 프로그래머에게는 pure 혹은 return 로, applyA\text{apply}_A ap 으로 많이 알려져있어요.

“이항 함수를 위한 Functor” 로서의 Applicative Functor

많으 사람들이 Applicative Functor 를 “이항 함수를 위한 Functor” 로 알고있어요. Applicative rules을 보존하면 자연스럽게 이항 함수(혹은 이항 연산자) 구조가 보존되기 때문이죠. 그리고 이는 너무나도 유용하고 많이 쓰여요. 이게 어떻게 가능한지 알아볼게요.
다른말로 어떤 이항 함수

+:X×YZ+:X\times Y \rightarrow Z

와 Applicative Functor AA
가 주여졌을때 우리는 다음과같은 새로운 이항 함수를 만들 수 있어요.
+A:AX×AYAZ +_A:AX \times AY \rightarrow AZ

그리고 이는 원래 이항함수의 성질을 그대로 이어받아요. e.g associativity, identity, commutativity etc.

왜 Functor 만으로는 이걸 할 수 없는지 생각해보는것도 많은 도움이 돼요. Functor 만으로 위 construction을 만들어 보려고 하면 금방 불가능하다는 것을 깨닳게 되죠. 이유는 object 로서의 함수가 등장하게 되는데, Functor 혼자선 apply 를 하기엔 너무 약하기 때문이죠. Functor는 함수가 object 가 아닌 morphism 으로서의 function 일 때만 apply 를 할 수 있어요.

아래와 같은 전개로써 construction 이 가능해요.

  • 를 currying 해 보면
:X(YZ) : X \rightarrow (Y \rightarrow Z)

이 나오죠.

+=η(+) +’ = \eta(+)

새로운 +' 의 타입은
A(X(YZ)) A(X \rightarrow (Y \rightarrow Z))

와 같아지는데 이제 여기에 applyA\text{apply}_A 를 적용해보면
+’’=applyA(+) +’’ = \text{apply}_A (+’)

그렇게 되면 새로운 +'' 의 타입은
AXA(YZ) AX \rightarrow A(Y \rightarrow Z)

함수가 된것을 볼 수가 있죠.
이 함수를 이제 applyA\text{apply}_A 와 함성해보면.
+A=applyA(+’’) +_A = \text{apply}_A(+’’)

이 돼요. +A +_A 의 타입은
+A:AXAYAZ +_A : AX \rightarrow AY \rightarrow AZ

이 되죠. 우리가 원하던 함수죠.

마무리

Applicative functor 는 너무나도 단순한 수학적 구조인 apply의 보존이에요. 어렵게 생각하실 것 하나도 없어요.

Discussion

pic
Editor guide