티스토리 뷰

iOS

모나드 Monad in swift

varyeun 2023. 9. 4. 16:36

구글과 나무위키를 타고타고 '모나드'를 검색해보면..

https://namu.wiki/w/Haskell/%EB%AA%A8%EB%82%98%EB%93%9C

 

Haskell/모나드 - 나무위키

타입 생성자 f에 대해 적절한 함수 fmap :: (a -> b) -> f a -> f b이 존재하여 다음 성질들을 만족할 때, f를 함자(Functor)라고 한다. 항등함수 id :: a -> a에 대해 fmap id :: f a -> f a도 항등함수다.모든 함수 f

namu.wiki

뭐.. 뭐라고요 ?

 

 

일단 모나드란. 여러 영역에서 다양한 뜻을 가지고 있는.. 아무도, 이거다!라고 정의할 수는 없지만.

내가 앞으로 설명할 3가지 조건들 중 하나라도(?) 갖추고 있는 것을 "모나드"라고 할 수 있다. 고는 말할 수 있음!

 

 

프로그래밍에서 모나드가 갖춰야할 조건 (동시에 다 만족해야하는 거 아님!)

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

 

이 글의 핵심임.

 

일단 이 세가지를 읽었을 때 떠오르는 걸 써보자면

1. 타입을 인자로 받는 타입 -> 제네릭이 떠오름. (T: ~ 이거.)

2. 3. 옵셔널 !!

 

난 스위프트를 쓰는 사람이니까 옵셔널로 모나드를 설명해보자.

 

 

Context와 Contents

- Context : 문맥, 상황

- Contents : 값

 

옵셔널은 Context고 그 안에 들어가는 값은 Contents 임.

옵셔널이라는 거 자체가 "값이 있을 수도 있고, 없을 수도 있는..." = 맥락?!문맥?상황? 이니까!

 

예) 팀원한테 "이 값 옵셔널이에요!" 라고 말하는 상상을 해보자. "이 값 있을 수도 있고, 없을 수도 있어요!" 라고 말하는 거랑 동일하지?

이 값 = Contents.

있을 수도 있고, 없을 수도 있어요! = Context = 옵셔널이에요

이해완.

 

2가 옵셔널이면

= "Context가 2라는 Contents를 갖고 있다" 

만약 nil인 옵셔널이면 ?

= "Context만 있디. Contents는 없음."

 

이렇게 되겠지...

 

 

이제 다시

let dd = Optional<Int>.init(2)
print(dd) //Optional(2)

이 코드와 함께

  1. 타입을 인자로 받는 타입(특정 타입의 값을 포장)
  2. 특정 타입의 값을 포장한 것을 반환하는 함수(메서드)가 존재

를 옵셔널을 설명하는 특징이라고 생각해보면 이해가 확 된다..

 

- Int라는 타입을 인자로 받았고요. (<Int>)

- Int라는 타입의 값(2)를 Optional로 포장해서 반환했고요. (init이 Optional(2)라고 포장함)

 

 

닫힌 함수객체 Endofunctor

함수객체란 ?

ㄴ 함수처럼 동작하는 객체.


자신의 Context와 같은 Context의 형태로 맵핑할 수 있는 함수객체를 '닫힌 함수객체'라고 하는데

모나드는 닫힌 함수객체임.

 

3. 포장된 값을 변환하여 같은 형태로 포장하는 함수(메서드)가 존재

 

왜냐면 이게 조건이니까.

 

그 예로 플랫맵(flatMap)을 들거임.

플랫맵은 간단하게 말하자면

예) n차원 배열이 있을 때, 그걸 평평하게 (= flat하게 만들고) map 을 적용시키는 map임(??

let dd = [[1, 2], [3, nil, 4]]
let d = dd.flatMap {
    $0.flatMap {
        $0
    }
}
print(d) //[1, 2, 3, 4]

일단 요지는 flatMap을 설명하고자 하는게 아니니까... 넘어가고

 

 

flatMap의 정의를 볼게요.

func flatMap<U>(_ transform: (Wrapped) throws -> U?) rethrows -> U?

무슨 말인지 모르겠다.

근데 이것만 보자

U? -> U? 

이 함수는 다 자르고 input output 만 보면 U? 가 들어가서 U?가 그대로 나온다.

 

 

그래서!

Optional(2)가 인자로 들어갔으면 이 말은 즉슨 Int? 가 들어간거니까 U는 Int가 됨. (U? = Int? -> U = Int)

 

그러면.

 

나올때 U? 가 나온다 했으니, Int? 가 나오겠지.. (U 자리에 Int 넣음)

=  포장된 값을 변환하여 같은 형태로 포장하는

가운데 글자는 흐리게 보고, 빨간 글자를 flatMap이 만족하고 있다는걸 알 수 있게됨.

(Optional로 포장된 값을 그대로 같은 Optional로 포장함..)

 

근데 flatMap이 무슨 함수였냐.. 뒤에 { } 로 들어오는 함수를 각각의 원소.

$0에 적용해서 반환하는 함수였잖아.

 

$0에 { } 안 내용을 적용 = "변환"

= 포장된 값을 변환하여 같은 형태로 포장하는

가운데 흐리게 보았던 글자가 make sense한 말이 된다.

 

결론적으로.

flatMap을 생각하면 "포장된 값을 변환하여 같은 형태로 포장하는 함수(메서드)가 존재" 라는 말이 이해가 된다...

 

 

그럼. 모나드 이해 완 ^^!

 

급 정리 끗.

 

이 좋은 예시와 설명들은

스위프트 프로그래밍 3판 by 야곰에서 배웠습니다.

댓글