[Swift] 모나드에 대해 알아보자!

zooneon·2020년 11월 15일
0

Swift 기본 문법

목록 보기
9/14
post-custom-banner

본 내용은 '스위프트 프로그래밍' 책을 학습한 후 이를 바탕으로 작성한 글입니다.

모나드

  • 모나드는 특정 기능이 아닌 디자인 패턴 혹은 자료구조라고 할 수 있다.
  • 프로그래밍에서 모나드가 갖춰야 하는 조건은 다음과 같다.
    1. 타입을 인자로 받는 타입(특정 타입의 값을 포장)
    2. 특정 타입의 값을 포장한 것을 반환하는 함수(메서드)가 존재
    3. 포장된 값을 변환하여 같은 형태로 포장하는 함수(메서드)가 존재
  • 모나드를 이해하기 위해 아래 개념을 잘 살펴보자

컨텍스트 - context

  • 컨텍스트context는 컨텐츠를 담은 상자 같은 것이다.
  • 함수의 전달인자로 컨텍스트가 다른 값을 전달하면 오류가 발생한다.
func addThree(_ num: Int) -> Int {
    return num + 3
}
//매개변수로 일반 Int 타입의 값을 받기 때문에 정상적으로 실행
addThree(2)
//전달인자가 순수한 값이 아닌 옵셔널이라는 컨텍스트로 둘러싸여 전달되었기 때문에 오류 발생
addThree(Optional(2))

함수객체 - functor

  • 함수객체functor란 맵map을 적용할 수 있는 컨테이너 타입이다.
  • Array, Dictionary, Set 등등 스위프트의 많은 컬렉션 타입이 함수객체이다.

플랫맵 flatMap 과 컴팩트맵 compactMap

  • 함수객체 중에서 자신의 컨텍스트와 같은 컨텍스트의 형태로 맵핑할 수 있는 함수객체를 닫힌 함수객체라고 하며, 모나드는 닫힌 함수객체이다.
  • 이런 맵핑을 수행하도록 플랫맵flatMap이라는 메서드를 활용한다.
  • 플랫맵 flatMap 은 맵 map 과 다르게 컨텍스트 내부의 컨텍스트를 모두 같은 위상으로 평평하게 펼쳐준다.
func doubleEven(_ num: Int) -> Int? {
    if num.isMultiple(of: 2) {
        return num * 2
    }
    return nil
}

Optional(3).flatMap(doubleEven)
//nil
  • compactMap은 스위프트 4.1 버전부터 flatMap이 하던 역할 중 하나를 맡게 되었다.
  • compactMap의 사용법은 flatMap과 같지만 좀 더 분명한 뜻을 나타내기 위해 compactMap이라는 이름을 사용한다.
let optionals: [Int?] = [1, 2, nil, 5]

let mapped: [Int?] = optionals.map{ $0 }
let compactMapped: [Int] = optionals.compactMap{ $0 }

print(mapped)    //[Optional(1), Optional(2), nil, Optional(5)]
print(compactMapped)    //[1, 2, 5] 
  • 만약 플랫맵 flatMap 을 사용하지 않으면서 플랫맵 flatMap 과 같은 효과를 얻으려면 바인딩을 직접 해주면 된다.
func stringToInteger(_ string: String) -> Int? {
    return Int(string)
}

func integerToString(_ integer: Int) -> String? {
    return "\(integer)"
}

var optionalString: String? = "2"
var result: Int?

if let string: String = optionalString {
    if let number: Int = stringToInteger(string) {
        if let finalString: String = integerToString(number) {
            if let finalNumber: Int = stringToInteger(finalString) {
                result = Optional(finalNumber)
            }
        }
    }
}

print(result)    //Optional(2)
  • 플랫맵 flatMap 은 체이닝 중간에, 연산에 실패하는 경우나 값이 없어지는 경우에는 별도의 예외 처리없이 빈 컨테이너를 반환한다.
func integerToNil(param: Int) -> String? {
    return nil
}

optionalString = "2"

result = optionalString.flatMap(stringToInteger).flatMap(integerToNil).flatMap(stringToInteger)

print(result)    //nil
profile
블로그 이전했습니다. https://blog.zooneon.dev
post-custom-banner

0개의 댓글