๊ทธ๋์ Monad๋ฅผ ์ ์ฌ์ฉํ๋๊ฐ?
์ ๋ชจ๋๋๊ฐ ์ ์ฉํ๊ฐ?
Improve High-Demensional lift
- Monad๋ Functor์ ๋ถ๋ง์กฑ์ค๋ฌ์ด ๋ถ๋ถ์ ํด์ํด์ค๋ค.
- ์์์
lift2d
์ ๋ํด ๋ฐฐ์ ๋ค. lift2d: ((T, U) -> V) -> (F<T>, F<U>) -> F<F<V>>
- ๋ฌธ์ ๋ ๋ฐํ ํ์ ์ ์ ๋ค๋ฆญ์ด ์ฌ๋ฌ๊ฐ ๊ฑธ๋ฆฐ๋ค๋ ๊ฒ์ด๋ค.
- ๊ฐ๋์ ์ ์ฉํ์ง๋ง ์ผ๋ฐ์ ์ผ๋ก๋ ๋ถํธํ๋ค.
list
๊ฐ์ ๊ฒ์ ์ ์ฉํ ์ ์์ง๋ง,optional
๊ฐ์ ๊ฒ์ ๋ณ ์ธ๋ฐ๊ฐ ์๋ค.- ์ฌ๊ธฐ์
flat
์ ์ฐ๋ฉด ๋ค์ค ์ ๋ค๋ฆญ์ ์ ๋ค๋ฆญ ํ๋๋ก ์ค์ผ ์ ์๋ค. - Functor์ Monad ์ฌ์ด์๋ Applicative Functor๋ผ๋ ๋จ๊ณ๊ฐ ํ๋ ๋ ์กด์ฌํ๊ธด ํ๋ค. ๋์ค์ ์์๋ณด์.
Enabld to compose Generic-returners
- ์์ ์ด์ ๋ณด๋ค ๋ ์ค์ํ ์ด์ ๊ฐ ์๋ค.
- ์ ๋ค๋ฆญ ํ์ ์ ๋ฐํํ๋ ํจ์๋ค์ ํฉ์ฑ์ ๊ฐ๋ฅ์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
T -> M<U>, U -> M<V>
๋๊ฐ์ ํจ์๊ฐ ์๋ค๊ณ ํ์.- ๋ณดํต์ ์ด ๋ ํจ์๋ฅผ ํฉ์ฑํ ์ ์๋ค.
- ์๋ํ๋ฉด
U
์M<U>
๋ ๋ค๋ฅธ ํ์ ์ด๊ธฐ ๋๋ฌธ์ด๋ค. - ๊ทธ๋ฐ๋ฐ Monad๋ ์ด๊ฒ ๊ฐ๋ฅํ๋ค. Monad๋
T
์ ์๋ฏธ๋ฅผ ์ ์งํ ์ํ๋ก ํ์ฅํ๋ ํ์ ์ด๋๊น.
// Optional
func f(_ t: T) -> Optional<U> {
// ...
}
func g(_ u: U) -> Optional<V> {
// ...
}
func gf(_ t: T) -> Optional<V> {
let opu = f(t)
switch opu {
case .none:
return .none
case .some(let u):
return g(u)
}
}
gf
์ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.- ์ด๊ฑด ํฉ์ฑํ ๊ฒฐ๊ณผ๋ฌผ์ ์๋๊ณ , ์ด๋ฐ ์์ผ๋ก ๋์ฌ ์ ์์์ ๋ณด์ฌ์ฃผ๊ธฐ ์ํจ์ด๋ค.
swift
์ ๊ฐ์ ์ธ์ด์์๋ ์ด๋ ๊ฒ ์ฒ๋ฆฌํ ์ ์๊ฒ ๋ค.
lift(g): Optional<U> -> Optional<Optional<V>>
flat o lift(g): Optional<U> -> Optional<V>
lift(g)
๋ฅผ ์ ์ฉํ๋ฉด ๊ฒฐ๊ณผ๊ฐ์ดOptional<Optional<V>>
๊ฐ ๋์จ๋ค.- ์ฌ๊ธฐ์ flat์ ์ด๋ ํ ๋ฐฉ์์ผ๋ก ๊ฑธ๋ฉด ์ํ๋ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
- Monad๋
flat
์ ๊ฐ์ง๊ณ ์์ผ๋ ์ด๋ฌํ ์์ผ๋ก ํ์ฅํ ์ฐ์ฐ์ ์ ์ํ ์ ์๊ฒ ๋๋ค. - ์ง์ ์ ์ํ ํ์๋ ์์ด Monad์ ํน์ฑ์ ๊ฐ์ง๊ณ ํฉ์ฑํ์ฌ ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค.
- ์ด์ ๊ฐ ์ก์๊ฒ ์ง๋ง ์ด๊ฑธ ์ ๊ณตํ๋ ๊ฒ์ด
flatMap
์ด๋ค.
func f(_ t: T) -> Optional<U> {
// ...
}
func g(_ u: U) -> Optional<V> {
// ...
}
let result = Optional(3)
.flatMap(f) // Optional<T> -> Optional<U>์ ํจ์๋ก ํ์ฅ
.flatMap(g) // Optional<U> -> Optional<V>์ ํจ์๋ก ํ์ฅ
lift
์ ๋ณํํจ์๋กOptional
์ด ๋ฆฌํด๋๋ ํจ์๋ฅผ ๋ฃ์์ผ๋, ๊ฒฐ๊ณผ๋ flatํด์ ๋์๋ค.- ์ด ๋์์ ์ฎ์ด์ ์ ๊ณตํ๋ ๊ฒ์ด
flatMap
์ด๋ค. flat o lift
, ๋ ํจ์๋ฅผ ํฉ์ฑํ ๊ฒ์ ๊ธฐ๋ณธ ์ ๊ณตํ๋ ๊ฒ์ดflatMap
์ด๋ค.
f: T -> M<U>
g: U -> M<V>
lift(g): M<U> -> M<M<V>>
flat o (lift(g)): M<U> -> M<V> // ์ด๋ ํ ๋ฐฉ์์ผ๋ก ํฉ์ฑํ๋ฉด~
(flat o (lift(g))) o f: T -> M<V> // ์ด๋ ํ ๋ฐฉ์์ผ๋ก ํฉ์ฑํ๋ฉด~
๊ฒฐ๋ก : flatLift(f) = flat o (lift(f))
- ์ ํํ ์ ๊ณ์ฐ์ด ์ด๋ ํ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ๋ค ์ค ๊ฒ์ด๋ผ ์๊ฐํ์ง๋ง๊ณ , ์ด๋ฐ ์์ผ๋ก ํฉ์ฑ์ด ๊ฐ๋ฅํ๋ค๋ ๊ฒ์ ์์๋์.
- o์ ๋์๋๋ ์ด๋ ํ ํฉ์ฑ ์ฐ์ฐ์ ๋ด๊ฐ ์ ๊ตฌํํ๋ฉด, ์ ์ฒ๋ผ
gf
ํจ์๋ฅผ ์ง์ ๋ง๋ค์ง ์๊ณ , - ๋ชจ๋๋์ ํน์ฑ์ ์ฌ์ฉํด์ ํฉ์ฑํ ์ ์๋ค.
flatLift
์ ์ญํจ์๋ก ๊ตฌํ
func flat<T>(_ value: Optional<Optional<T>>) -> Optional<T> {
switch value {
case .none:
return .none
case .some(let wrapped):
return wrapped
}
}
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))
}
}
}
func flatLift<T, U>(_ transform: @escaping (T) -> Optional<U>) -> ((Optional<T>) -> Optional<U>) {
return { (input: Optional<T>) -> Optional<U> in
flat(
lift(transform) // Optional<T> -> Optional<Optional<U>>
(input) // Optional<Optional<U>>
) // Optional<U>
}
}
// ๋ค์ ์ฐ๋ฉด,
func flatLift<T, U>(_ transform: @escaping (T) -> Optional<U>) -> ((Optional<T>) -> Optional<U>) {
{ input in
flat(lift(transform)(input))
}
}
Extension์ผ๋ก ๊ตฌํ
internal enum Optional<T> {
case none
case some(T)
}
extension Optional {
internal func flat<T>(_ oot: Optional<Optional<T>>) -> Optional<T> {
switch oot {
case .none:
return .none
case .some(let ot):
return ot
}
}
internal func lift<T, U>(_ transform: @escaping (T) -> U) -> (Optional<T>) -> Optional<U> {
{ input in
switch input {
case .none:
return .none
case .some(let wrapped):
return .some(transform(wrapped))
}
}
}
internal func flatLift<T, U>(_ transform: @escaping (T) -> Optional<U>) -> ((Optional<T>) -> Optional<U>) {
{ input in
flat(lift(transform)(input))
}
}
}
High-Demensional lift with FlatLift
- ๊ทธ๋ผ
lift
์ฒ๋ผflatLift
์ ๋ค๋ณ์ํจ์์ ์ ์ฉํ ์ ์๋๊ฐ? - ๋น์ฐํ ๋๋ค.
flatLift
๊ฐlift
์์๋ณด๋ค ๋ค๋ณ์ ํจ์์์ ๋ณด๋ค ๋ ์ ์ฉํ๋ค.- ์ด๋ ๋น์ฐํ
flat
ํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
flatLift2d: ((T, U) -> M<V>) -> ((M<T>, M<U>) -> M<V>)
lift
์ ๊ฒฝ์ฐ ์ฐจ์ ํ์ฅ์, ๋ณ์ ๊ฐ์์ ๋ฐ๋ผ ๋ฐํ ํ์ ์ ์ ๋ค๋ฆญ์ด ์ค์ฒฉ๋์์ง๋ง,flatLift
์ ๊ฒฝ์ฐ ์ฐจ์ ํ์ฅ์, ๋ณ์ ๊ฐ์์ ๋ฐ๋ผ ๋ฐํ ํ์ ์ ์ ๋ค๋ฆญ์ด ์ค์ฒฉ๋์ง ์๋๋ค.- ์ด๋ ์์ฒญ๋๊ฒ ์์ฃผ ์ฌ์ฉ๋๋๋ฐ, ๊ทธ ๋๋ฌธ์ ์ผ๋ถ ์ธ์ด์์๋ ์ด๋ฅผ ์ํ ์ถ์ฝ ํ๊ธฐ๋ฅผ ์ ๊ณตํ ์ ๋์ด๋ค.
do
(Haskell),for
(Scala)
flatLift2d
- ์์์ ์ฐจ์ ํ์ฅ์ผ๋ก ๊ณ ์์ ๋ค ํ๊ธฐ ๋๋ฌธ์ ์๋ ์ฝ๋ค!
func lift<T, U>(_ transform: @escaping (T) -> U) -> (T?) -> U? {
{ input in
switch input {
case .none:
return .none
case .some(let wrapped):
return .some(transform(wrapped))
}
}
}
func flat<T>(_ value: T??) -> T? {
switch value {
case .none:
return .none
case .some(let wrapped):
return wrapped
}
}
func flatLift<T, U>(_ transform: @escaping (T) -> U?) -> (T?) -> U? {
{ input in
flat(lift(transform)(input))
}
}
func flatLift2d<T1, T2, U>(_ transform: @escaping (T1, T2) -> U?) -> (T1?, T2?) -> U? {
{ mt1, mt2 in
flat(lift { t1 in
flat(lift { t2 in
transform(t1, t2)
}(mt2))
}(mt1))
}
}
func flatLift2d<T1, T2, U>(_ transform: @escaping (T1, T2) -> U?) -> (T1?, T2?) -> U? {
{ mt1, mt2 in
flatLift { t1 in
flatLift { t2 in
transform(t1, t2)
}(mt2)
}(mt1)
}
}
func flatLift3d<T1, T2, T3, U>(_ transform: @escaping (T1, T2, T3) -> U?) -> (T1?, T2?, T3?) -> U? {
{ mt1, mt2, mt3 in
flatLift { t1 in
flatLift { t2 in
flatLift { t3 in
transform(t1, t2, t3)
}(mt3)
}(mt2)
}(mt1)
}
}
flatLift์ ๊ฐ ๋ฃ์ด๋ณด๊ธฐ
Optional
- ์์์ ํจ์ f๊ฐ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์๋ค๊ณ ํ์.
f: (T, U) -> Optional<V>
let opt: Optional<T>
let opu: Optional<U>
lift2d(f)(opt, opu)
flatLift2d(f)(opt, opu)
- ์,
lift
๋ฅผ ๋ง์ฝ์ ๊ฑธ์๋ค๋ฉด ์๊ณผ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์์ ๊ฒ์ด๋ค.
flatLift
๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ๋๋ค.- ๋๋ค ๊ฐ์ด ์๋ ๊ฒฝ์ฐ๋ง ์ ๋๋ก ๋จ์ด์ง๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ๋น ์ต์ ๋์ด ๋์จ๋ค.
- ๋๋จธ์ง ๊ฒฝ์ฐ๋ฅผ ํ๋์ ํ์ ์ผ๋ก ์์ถํด์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ค.
- 3์ฐจ์์ด๋ฉด ์๋ง ์ ์ก๋ฉด์ฒด์ ํํ๋ก ๋ชจ์์ด ๋์ค๊ณ , ํ ์ ์ ์ ์ธํ ๋๋จธ์ง๊ฐ none์ผ๋ก ๋จ์ด์ง ๊ฒ์ด๋ค.
List
- ์์์ ํจ์ f๊ฐ ๋ค์๊ณผ ๊ฐ์ด ์ ์๋์๋ค๊ณ ํ์.
f: (T, U) -> [V]
let left = [t1, t2, t3]
let right = [u1, u2]
lift2d(f)(left, right)
flatLift2d(f)(left, right)
lift2d
๋ฅผ ๊ฑธ๋ฉด ์ด๋ ๊ฒ ๋์จ๋ค.
[
[f(t1, u1), f(t1, u2)],
[f(t2, u1), f(t2, u2)],
[f(t3, u1), f(t3, u2)]
]
flatLift2d
๋ฅผ ๊ฑธ๋ฉด ์ด๋ ๊ฒ ๋์จ๋ค.
[
f(t1, u1),
f(t1, u2),
f(t2, u1),
f(t2, u2),
f(t3, u1),
f(t3, u2)
]
๊ทธ๋์ flatLift๋?
flatLift: `((T1, T2โฆ) โ M) โ ((M
, M โฆ) โ M)๋ก ๋ณํํด์ฃผ๋ ํจ์
((T1, T2...) -> U)
๋ก ๋ณํํจ์๊ฐ ๋ค์ด์ค๋ฉด?- ๊ทธ๊ฒ๋ ์์ ํํ๋ก ๋ง๋ค ์ ์๋ค.
- ๋ฆฌํดํ ๋ U์
unit
ํจ์ ๊ฑธ์ด์ฃผ๋ฉด ๋๋ค.