공부한 것
- monad
- functor
- context
- applicative
처음에 고민한 점 및 생각해본 점
- 일단 가장 근본적으로, monad가 뭘까?
- monad는 함수형 프로그래밍에서 자주 등장하곤 하는 녀석이다. 다분히 수학적인 개념에서 출발한 듯 한데, 겁먹기 쉬운 것 같다..
- monad에 대해서만 알고 싶었을 뿐인데, 흰개미집을 건드린 것처럼 용어들이 튀어나왔다. functor, applicative, context...
- 그래서 하나씩 하나씩 역추적해보기로 했다!
Context
- 이 연쇄를 풀어내기 위해 가장 먼저 알아야 할 개념은 Context라고 판단했다.
- Context란 직역하면 맥락. 내가 이해한 개념은 "포장지" 이다.
- 특정한 Context라는 박스 안에 구체적인 값이 들어있(을 수도 있고 아닐 수도 있)는 모양을 취하고 있다.
- 하단의 카카오 아티클과 외국 블로그 아티클을 참고하고, 조금은 감을 잡을 수 있었다. 왜 활동학습 시간에 옵셔널 이야기가 나왔는지, 카카오 아티클의 작성자분이 왜 Rx의 창시자에게 가르침을 받아야 했는지.
- 이전에 Rx 없이 Boxing 방법을 통해 MVVM을 구현해 보면서 경험한 것이 큰 도움이 되었다.
- 스위프트의 옵셔널 값은 "옵셔널" 이라는 박스(Context)에 담겨 있는 것이다. 이 박스 안에는 값이 있을 수도 있고 없을 수도 있다. 하지만 아무튼, 옵셔널이라는 박스에 감싸여 있으므로, 옵셔널이라는 속성(맥락)을 가진 값이 된다.
- Boxing 방법을 사용할 때도, 값의 변화를 감지하고 바꿔 주는
Box
자료형이 일종의 Context인 셈이다.
final class Box<T> {
typealias Listener = (T) -> Void
var listener: Listener?
var value: T {
didSet {
listener?(value)
}
}
init(_ value: T) {
self.value = value
}
func bind(listener: Listener?) {
self.listener = listener
listener?(value)
}
}
- Rx에서도, Observable, Disposable 등의 속성, 즉 포장지가 Context라고 볼 수 있겠다.
Functor
- Context에 싸인 값에 우리가 통상적으로 쓰던 메서드를 쓸 수 없는 경우가 많다.
- Functor는 Type class. 타입 클래스란, 어떤 행동을 하는 법에 대해 정의해 둔 것이다. 객체지향 언어의 클래스와 혼동하기 쉬운데, 클래스랑은 다른 것!
- 즉, Functor는 Context 안의 값에 대해 어떤 행동(Function)을 적용하는 역할을 한다. 상자 속 값에 함수 적용하기!
- swift 안에서는 주로
map
을 내부적으로 사용하곤 한다.
- 왜 Functor 이야기를 하면서
map
얘기도 나오는지 알 수 있다. map
은 주어진 시퀀스의 원소들에 대해 주어진 동작(transform
파라미터 안에 들어가는 클로저)을 수행해, 변환된 값들의 배열을 반환한다. transform
이라는 동작(함수)을 Sequence
라는 Context 안의 값들에 적용시키기 위한 Functor가 바로 map
인 셈이다.
- 그렇기 때문에 동일한 방법론을 적용한 자체 제작 메서드도
map
을 사용해 구현하는 것이 편한 것.
Applicative
- 앞에서, Functor는 Context로 싸여 있는 값에 어떤 행동(보통 함수)을 가하기 위해 쓴다고 했다.
- 그런데, Context에 싸여 있는 값에 Context에 싸여 있는 함수를 적용하고 싶다면 어떡하지??
- 이럴 때 사용하는 것이 Applicative. 상자 속 함수를 상자 속 값에 적용한다.
- swift 안에서는, 함수 안에서 switch-case를 통해 값이 있는지 없는지 판별하고,
map
또는 이를 채용한 함수를 적용할 수 있겠다.
그래서, Monad
- Monad는 원래 수학의 범주론에서 사용되던 구조이나, Haskell이나 Scala 같은 언어에서 이를 프로그래밍 언어에 적용했다. Monad와 함수형 프로그래밍이라는 키워드가 항상 같이 나오는 것은 이 때문..
- Context를 상자라고 했었지? Monad는 상자 속에 있는 값에 함수를 적용시켜, 값이 들어있는 "상자"를 반환할 수 있다.
- Monad 형을 활용하면, 최종적으로 원하는 값의 모양을 가지고 있는 (== 원하는 Context에 들어 있는) 값을 반환할 수 있다.
- Functor는 Context 안의 값에 함수 적용시키기, Applicative는 Context 안의 값에 Context 안의 함수 적용시키기, Monad는 Context 안의 값에 함수를 적용시켜 원하는 Context에 담아 반환하기.
- 오늘 끝날 주제가 아님이 느껴진다. 종종 생각나면 찾아보도록 하자.
- 하지만 의외로 Monad는 우리 가까이에 있을지도 모른다..
참조