Functor๋ ๋ฌด์์ธ๊ฐ?
Functor
Functor: ์์์ ํ์
T, U
๊ฐ ์ฃผ์ด์ก์ ๋, ์ฐ์ฐ lift์ด ์ ์๋๋ 01. Type ConstructorF
lift:
(T -> U) -> (F(<T>) -> F(<U>))
T->U
์ธ ํจ์๊ฐ ์์ ๋, ๊ฐ๊ฐ์ ์์๋ฅผ 01. Type ConstructorF
๋ก ๊ฐ์ธ๋ ํจ์๋ก ๋ณํํ ์ ์์ผ๋ฉด Functor- ์ฌ๊ธฐ์
(T->U)
๋ก ๊ฐ๋ ๊ฑด ๋ด๋ถ์ ๋ค์ด๊ฐ ๊ฐ์ ๋ณํ ํ๋ ๊ฒ์ด๋ค. ์ด์ ๋ถํฐ ์ด๊ฑธtransform
์ด๋ผ ๋ถ๋ฅด๊ฒ ๋ค. - ๋์ ํด์ ์๊ฐํด๋ณด์.
Optional
internal func lift<T, U>(_ transform: @escaping (T) -> U) -> (Optional<T>) -> Optional<U> {
return { (input: Optional<T>) -> Optional<U> in
switch input {
case .none:
return .none
case .some(let wrapped):
return .some(transform(wrapped))
}
}
}
transform
์ ์ธ์๋ก ๋ฐ์Optional<T>
๋ฅผ ์ธ์๋ก ๋ฐ์Optional<U>
๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๋ฐํํ๋ค.- ์ด๊ฒ ๋ช
ํํ ์ ์๋๋
Optional
์ Functor์ด๋ค.
Array
internal func lift<T, U>(_ transform: @escaping (T) -> U) -> ([T]) -> [U] {
return { (input: [T]) -> [U] in
var result: [U] = []
for index in input.indices {
result.append(transform(input[index]))
}
return result
}
}
Result
internal func lift<T, U>(_ transform: @escaping (T) -> U) -> (Result<T, Error>) -> Result<U, Error> {
return { (input: Result<T, Error>) -> Result<U, Error> in
switch input {
case .failure(let error):
return .failure(error)
case .success(let value):
return .success(transform(value))
}
}
}
๋ณดํต์ ํํ ๋ฐฉ๋ฒ
- ๋ณดํต์ ์ ๋ ๊ฒ
<T, U>
๋ฅผ ์ง์ ์ ์ธํด๋์ง ์๊ณ , ํ์ ๋ด์์ ๊ฒฐ๊ณผ ํ์ ๋ง ๊ฐ์ง๊ณ ์์ ์ ์๊ฒ ์์์ ๊ตฌํํ๋ค. - ๋ชจ๋ Functor์ ๋์๋๋ ์๋ฃ๊ตฌ์กฐ๊ฐ ๋ค ์ ๊ตฌํ์ฒด๋ฅผ ๊ฐ๊ณ ์์ง๋ ์์ผ๋ฉฐ,
Array
,Set
๊ณผ ๊ฐ์ดSequence
๋ก ๋ฌถ์ด๋ ๊ฒฝ์ฐ์๋ ์์ ํ์ ์ ํ๋กํ ์ฝ์ด๋ ํด๋์ค์์ ๊ตฌํํด๋๋ค. - ์ด ๋ถ๋ถ์ ์ธ์ด๋ง๋ค ๊ตฌํ์ด ๋ฌ๋ผ ๊ฐ๋ ์ ์ผ๋ก ์ดํดํ๋ ๊ฒ์ด ์ข์ ๋ฏ.
internal enum Optional<Wrapped> {
case none
case some(Wrapped)
func map<U>(_ transform: (Wrapped) throws -> U) rethrows -> U? {
switch self {
case .none:
return .none
case .some(let wrapped):
return try .some(transform(wrapped))
}
}
}
- ๋ณดํต
lift
๋ผ ๊ตฌํ ์๋์ด ์๊ณmap
์ผ๋ก ๋์ด ์๋ค.
์ด๋ป๊ฒ Functor๋ฅผ ๊ตฌํํ ๊น?
- ์ด์ ์์์ ๋ํ์ ์ธ Type Constructor๋ค์ด Functor์์ ์์๋ค.
- ์ฆ,
Optional
,Array
,Result
๋ Functor์ด๋ค. - ๊ทธ๋ ๋ค๋ฉด ๋ณดํต ์ฐ๋ฆฌ๋ ์ด๊ฑธ ์ด๋ป๊ฒ ๊ตฌํํ ๊น?
Functor
๋ผ๋ ํ๋กํ ์ฝ์ ๋ง๋ค๋ , ํด๋์ค๋ฅผ ๋ง๋ค๋ ํ ๋ค์์ ์ด๊ฑธ ์์ํ๊ฒ ํด์ ๊ธฐ๋ณธ ๋์์ ์ ๊ณตํ ๊ฒ์ด๋ค.
- ๊ทธ๋ฐ๋ฐ Swift์์ ๋ณด์์ ๋๋ ์์ ํ ์ด๋ฐ ๊ฐ๋ ๋๋ก ๊ตฌํ๋ ๊ฒ ๊ฐ์ง๋ ์๋ค.
Set
,Array
๊ฐ์ ๊ฒฝ์ฐ๋Sequence
Protocol์ ์์๋ฐ์ ์ฒ๋ฆฌ๋๊ณ ,Optional
์ ๊ฒฝ์ฐ์๋ ์์ฒด์ ์ผ๋ก ๊ฐ์ง๊ณ ์๋ค.- ์ ์ด๋ ๊ฒ ์ฒ๋ฆฌํ๋์ง๋ ์ถ๊ฐ์ ์ผ๋ก ์์๋ด์ผ ํ ๋ฏ.
Functor lift ํจ์์ ์ถ๊ฐ ์กฐ๊ฑด
- ์์์ ์ด๋ ค์ธ๊น๋ด ์์ ์๋ค.
- lift ํจ์๋
T->U
๋ก ๊ฐ๋ ํจ์๋ฅผ ๋ฐ์F(T)
๋ฅผ ๋ฐ์F(U)
๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ๋ฐํํ๋ค. - ์ด lift ํจ์๊ฐ ๋ง์กฑํด์ผ ํ๋ ๋๊ฐ์ง ์กฐ๊ฑด์ด ์๋ค.
ํจ์์ ํญ๋ฑ์ฑ
id_T = (T -> T)
id_F<T> = (F(T) -> F(T))
lift = (X -> Y) -> (F<X> -> F<Y>)
lift(id_T) = id_F<T>
- ํญ๋ฑํจ์๋ฅผ id๋ผ ํ์. (identity)
T->T
์ธ ํญ๋ฑํจ์๋id_T
๋ผ๊ณ ํํํ ์ ์๋ค.F(T)->F(T)
์ธ ํญ๋ฑํจ์๋id_F<T>
๋ผ๊ณ ํํํ ์ ์๋ค.- lift ์ด๋ผ๋ ํจ์๋
(X -> Y) -> (F<X> -> F<Y>)
๋ผ๊ณ ํํํ ์ ์๋๋ฐ, ์ด ์ฐ์ฐ์ ๊ฒฐ๊ณผ๋ ๋ญ๊ฐ ๋์ฌ์ง ๋ชจ๋ฅธ๋ค. - ๊ทธ๋ฐ๋ฐ lift์ ์ธ์๋ก ํญ๋ฑํจ์๋ฅผ ๋ฃ์๋ค๋ฉด, ๊ฒฐ๊ณผ ์ญ์ ํญ๋ฑํจ์๊ฐ ๋์์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
- ์ฌ์ค ํํ๋ง ๋ด์๋ ์๋ช ํ๊ฒ ๊ทธ๋ฐ ๊ฒ ๊ฐ์ผ๋, ์ํ์ ์ผ๋ก ์๋ฐํ๊ฒ ์ ์ํ๊ธฐ ์ํ ๊ฒ์ ๊ฐ๊น๋ค.
- (๊ทธ๋์ ๊ฐ์ฅ ๋ฐ์ ๋ฃ์๋ค.)
ํจ์์ ํฉ์ฑ ๊ด๊ณ ๋ณด์กด
f = (T -> U)
g = (U -> V)
lift = (X -> Y) -> (F<X> -> F<Y>)
h = gโf
lift(h) = lift(gโf) = lift(g)โlift(f)
์ฆ,
lift(gโf) = lift(g)โlift(f)
- ํจ์
h
๊ฐg
์f
์ ํฉ์ฑ์ด๋ผ๊ณ ํ๋ค๋ฉด, - ์ด
h
๋ฅผlift
ํ ๊ฒฐ๊ณผ ์ญ์g
์f
๋ฅผlift
ํ ๊ฒฐ๊ณผ์ ํฉ์ฑ๊ณผ ๊ฐ๋ค. (lift(g)โlift(f)
)
func f(_ x: Int) -> Int {
return x + 1
}
func g(_ x: Int) -> Int {
return x * 2
}
func h(_ x: Int) -> Int {
return g(f(x))
}
let optional = Optional.some(10)
let result1 = lift({ h($0) })(optional) // Optional.some(22)
let result2 = lift({ g($0) })(lift({ f($0) })(optional)) // Optional.some(22)
let array = [3, 4, 5, 6]
let result1 = lift({ h($0) })(array) // [8, 10, 12, 14]
let result2 = lift({ g($0) })(lift({ f($0) })(array)) // [8, 10, 12, 14]
let result: Result<Int, Error> = .success(10)
let result1 = lift({ h($0) })(result) // success(22)
let result2 = lift({ g($0) })(lift({ f($0) })(result)) // success(22)
- ์ด๊ฒ๋ ์๋ฐํ ์ฆ๋ช ์ ๋ชปํ๊ฒ ์ง๋ง ๊ฒฝํ์ ์ผ๋ก ์ฐธ์์ ์ด๋ ต์ง ์๊ฒ ์ ์ ์๋ค.
- (๊ทธ๋์ ๊ฐ์ฅ ๋ฐ์ ๋ฃ์๋ค.)