[스위프트 프로그래밍-16장] 모나드

sanghee·2021년 11월 22일
1
post-thumbnail

이 글은 스위프트 프로그래밍(3판, 야곰 지음)을 읽고 간단하게 정리한 글입니다. 책에 친절한 설명과 관련 예제 코드들이 있으므로 직접 사서 읽기를 추천합니다.

16.0 소개

함수형 프로그래밍에서 모나드는 순서가 있느 연산을 처리할 때 자주 활용되는 디자인 패턴이다. 프로그래밍에서 사용되는 모나드는 모나드의 의미를 완벽히 구현하려고 하지 않기에 차용한 정도의 의미를 갖는데, 이를 모나딕이라고도 표현한다.

프로그래밍에서 모나드가 갖춰야 할 조건은 다음과 같다.

  1. 타입을 인자로 받는 타입이다(특정 타입의 값을 포장한다).
  2. 특정 타입의 값을 포장한 것을 반환하는 함수(메서드)가 존재한다.
  3. 포장된 값을 변환하여 같은 형태로 포장하는 함수(메서드)가 존재한다.

옵셔널

모나드는 값을 무엇으로 포장하는 개념이다. 스위프트에서 모나드를 사용한 예 중에 하나가 옵셔널이다. 옵셔널은 값이 있을지 없을지 모르는 상태를 포장한 것이다.

16.1 컨텍스트

컨텍스트(Context)와 콘텐츠(Content)

컨텍스트란 맥락, 전후 사정이라는 의미이다. 여기에서는 콘텐츠를 담고 있는 무언가를 의미한다. 물이 담긴 물컵이라면, 물은 콘텐츠이고 물컵은 물을 담고 있는 컨텍스트이다.

옵셔널을 다시 예로 들어본다. 옵셔널은 열겨형 case로 구현되어 있다. 값이 있다면 some 케이스로, 없다면 none 케이스로 값을 지니게 된다. Optional(2)라면 2라는 숫자를 Optional이라는 상자로 감싼 것이다. 반대로 옵셔널 안에 값이 없어 nil이라면, 빈 상태를 Optional로 감싼 것이라고 이해하면 된다.

Optional(2)

nil

16.2 함수객체

맵(map)은 컨테이너의 값을 변형시킬 수 있는 고차함수이다. 그리고 옵셔널은 컨테이너와 값을 갖기 때문에 맵 함수를 사용할 수 있다. 옵셔널이지만 어떻게 컨테이너 내부의 2값을 가지고 적용할 수 있을까?

let result = Optional(2).map { $0 * 2 }
print(result) // Optional(4)

연산 과정

  1. 옵셔널 상자에서 2를 꺼낸다.
  2. 값이 있기 때문에 2를 곱한다. 만약 값이 없다면 연산을 하지 않는다
  3. 나온 결과값 4를 다시 옵셔널 상자에 넣는다.
  4. 옵셔널 4를 반환한다.

16.3 모나드

자신의 컨텍스트와 같은 컨텍스트의 형태로 맵핑할 수 있는 함수객체를 닫힌 함수객체라고 한다. 모나드는 닫힌 함수객체이다.
모나드를 쉽게 설명하자면 flatMap 연산이 가능한 모든 것들을 우리는 모나드라고 부를 수 있다.

map, compactMap, flatMap 차이

compactMap과 flatMap은 1차원 배열의 nil값을 없앤다. 둘의 차이로는, flatMap은 compactMap과 다르게 기존의 배열을 1단계 평평하게 만들어 반환한다.

let array = [[1, 2, nil], [4, nil]]

let a = array.map { $0.map { $0 } }
let b = array.compactMap { $0.compactMap { $0 } }
let c = array.flatMap { $0.flatMap { $0 } }

print(a) // [[Optional(1), Optional(2), nil], [Optional(4), nil]]
print(b) // [[1, 2], [4]]
print(c) // [1, 2, 4]
profile
👩‍💻

0개의 댓글