함수 합성 함수의 합성 - (.).(.)
Tags: mathematics, haskell, categorytheory, functional
Published: 2020-06-18 13:30:57

---
title: 함수 합성 함수의 합성 - (.).(.)
published: true
description: 
tags: mathematics, haskell, categorytheory, functional
//cover_image: https://direct_url_to_image.jpg
---


코도메인(codomain)과 도메인(domain)이 같은 두 함수의 합성(composition)은 익숙하실거에요.

{% katex %}
f : B \rightarrow C \newline
g : A \rightarrow B \newline
h = f \circ g \newline
h: A \rightarrow C
{% endkatex %}

근데 함수 합성 자체도 함수죠? 그렇다면 함수 합성 함수를 합성하면 어떤함수가 될까요?

{% katex %}
(\circ) \circ (\circ) = ?
{% endkatex %}

결론부터 말하자면 일항함수와 이항함수를 합성할 수 있는 새로운 합성함수가 탄생해요. 즉

{% katex %}
f: C \rightarrow D \newline
g: A \times B \rightarrow C
{% endkatex %}

일때 {% katex inline %} h {% endkatex %} 를 다음과 같이 정의하면
{% katex %}
h = f \left( (\circ) \circ (\circ) \right) g 
{% endkatex %}

{% katex inline %} h {% endkatex %} 는 다음과같아요

{% katex %}
h : A \times B \rightarrow D \newline
h(a,b) = f(g(a,b))
{% endkatex %}

한발 더 나아가서 함수합성함수 세개를 합성한다면?!

{% katex %}
f : D \rightarrow E \newline
g : A \times B \times C \rightarrow D \newline
h : A \times B \times C \rightarrow E \newline
h = f \left( (\circ) \circ (\circ) \circ (\circ) \right) g \newline
h(a,b,c) = f(g(a,b,c))
{% endkatex %}

일항 함수와 삼항 함수를 합성할 수 있는 새로운 합성자가 생기죠. 즉 도메인의 차수가 하나 더 늘어나는거에요.

왜그런지 이해하기 위한 가장 쉬운 방법으로는 직접 증명 해보는 방법이 있어요. 대략적으로 증명하자면 다음과 같아요. (이 글의 목적은 직접 증명을 설명하는게 아니므로 친절한 설명은 생략할게요)

> 합성은 다음과 같은 모양이므로.
> 
> {% katex %}
> \circ: (\beta \rightarrow \gamma) \times (\alpha \rightarrow \beta) \rightarrow (\alpha \rightarrow \gamma)
> {% endkatex %}
>
>여기서 파라메터 둘 다 합성함수 이므로 필연적으로 {% katex inline %}\alpha, \beta, \gamma{% endkatex %}도 다음과 같은 모양을 띄게 된다.
>
>{% katex %}
>\alpha : y \rightarrow z \newline
>\beta : (x \rightarrow y) \rightarrow (x \rightarrow z) \newline
>\gamma : (a \rightarrow (x \rightarrow y)) \rightarrow (a \rightarrow (x \rightarrow z))
>{% endkatex %}
>
>그러므로 다음과같이 일항 함수와 이항 함수의 합성함수의 모양을 띄게 된다.
>
>{% katex %}
>\alpha \rightarrow \gamma = (y \rightarrow z) \rightarrow (a \rightarrow x \rightarrow y) \rightarrow (a \rightarrow x \rightarrow z)
>{% endkatex %}

어렵지 않게 결론에 도달할 수 있을거에요.

하지만 이 방법은 단순히 명제의 참거짓 여부만 판단할 수 있을뿐 정작 **왜** 라는 물음에는 답해주지 않죠. 함수 합성은 어떤 성질이 있길래 둘을 합성하면 이런 마법같은 효과가 있는걸까요? 만약 [홈펑터 (Hom functor)](https://en.wikipedia.org/wiki/Hom_functor) 라는 개념을 알고있다면 더 나은 설명이 가능해요.

카테고리 이론의 시점에서 함수 합성은 홈펑터에요. 임의의 두 함수의 합성을 홈펑터로 나타내본다면 다음과 같아요.

{% katex %}
\circ_{hom(x,-)} : (y \rightarrow z) \rightarrow (y^x \rightarrow z^x)
{% endkatex %}

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/en7xeob875mxeqt9w06r.jpeg)

> ###### 여기서 {% katex inline %}x^y{% endkatex %}는 {% katex inline %}y \rightarrow x{% endkatex %}와 같아요.

그리고 우리가 원하는 더블 합성은 다음과 같죠.

{% katex %}
\circ_{hom(x,-)} \circ \circ_{hom(a,-)} : (y \rightarrow z) \rightarrow (y^{xa} \rightarrow z^{xa})
{% endkatex %}

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/10gv67usuo2uuuaurmtr.jpeg)

{% katex inline %} f: y\rightarrow z {%endkatex%} 와 {% katex inline %} g: x\times a \rightarrow y {%endkatex%} 만 있으면 더블 펑터 합성을 이용해서 {% katex inline %} h: x\times a \rightarrow z {%endkatex%}을 만들 수 있게 되는거죠.

하스켈에서 2차원 벡터의 길이를 구하는 코드를 예로 들어볼게요. 보통 벡터를 다루는 라이브러리들은 꼭 필요한 상황이 아닌이상은 퍼포먼스를 위해 벡터의 길이보다는 제곱근을 적용하기 전의 벡터길이를 사용하는것을 권장해요. 여기서도 제곱근 이전 길이를 구하는 함수 `squaredMagnitude`함수를 구현한 후, 실제 길이를 구하는 `magnitude`함수를 위에서 논한 방법을 이용해서 제곱근 함수와 `squaredMagnitude`를 합성해서 구현을 해 볼게요.

```haskell
(.*) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.*) = (.) . (.)

squaredMagnitude :: Double -> Double -> Double
squaredMagnitude x y = x^2 + y^2

magnitude = sqrt .* squaredMagnitude

main :: IO ()
main = do
  print $ squaredMagnitude 3 4
  print $ magnitude 3 4
```

결과는 다음과 같아요

```shell
25.0
5.0
```