Monad์ Functor ์ฌ์ด์๋ Monoidal Functor๋ผ๋ ์ค๊ฐ ๋จ๊ณ๊ฐ ์๋ค.
Monoidal Functor๋ฅผ ์ ์ํ ์ ์๋ ์ธ์ด
์๋ฌด ์ธ์ด์์๋ ์ ์๋ ์ ์๋ ๊ฐ๋ ์ ์๋๋ค. ๋ค์์ ์กฐ๊ฑด์ด ์ ํ๋์ด์ผ ํ๋ค.
- Empty Type ์ ์ ๊ณตํด์ผ ํ๋ค.
Void
()
- C์์ ๋น ๊ตฌ์กฐ์ฒด ๋ฑ
T, U
ํ์ ์ ๋ํ Pair๋ฅผ ๋ง๋ค ์ ์๋ ํํ ํ์ ๋ฅผ ์ ๊ณตํด์ผ ํ๋ค.- ํํ ํ์
๊ณผ ๋น ํ์
์ ๋ค์์ ํจ์๋ฅผ ์ ๊ณตํด์ผ ํ๋ค.
empty
: - ๋น ํํ์ ๋ง๋ค์ด์คunite
: - ๋ ๊ฐ์ ํํ๋ก ๋ฌถ์ด์คe1
:e2
:
์ฆ, ๋ค์์ ๋ง์กฑํด์ผ ํ๋ค.
unite(e1(u), e2(u)) = u
internal func empty() -> Void {
()
}
internal func unite<T, U>(_ t: T, _ u: U) -> (T, U) {
(t, u)
}
internal func e1<T, U>(_ tu: (T, U)) -> T {
tu.0
}
internal func e2<T, U>(_ tu: (T, U)) -> U {
tu.1
}
unite ํ์ํจ์๋ค
n๊ฐ์ ๊ฐ์ n๊ฐ๊ฐ ํ๋์ ํ์
์์ ๋ค์ด๊ฐ๋๋ก ํ๋ unite_n
์ ์์๋ณด์.
์ฆ, n๊ฐ ์ธ์๋ฅผ ํ๋์ ์ธ์๋ก ๋ฐ๊ฟ์ค๋ค.
unite_0 = empty
unite_1 = identity
unite_{n}(t1, ..., tn) = unite(unite_{n-1}(t1, ..., t{n-1}), t{n})
unite3(t1, t2, t3)
= unite1(unite2(t1, t2), t3)
= unite1(unite1(unite1(t1), unite1(t2)), unite1(t3))
- ํ์ง๋ง ์ด ํจ์๋ ์์ ๊ตฌํ์ด swift๋ก ๋ถ๊ฐํ๋ค.
- tuple์ด๋ผ๋ ์๋ฃ๊ตฌ์กฐ์ ์ธ์ ๊ฐ์๋ฅผ ๋ถํน์ ํ ์ํ๋ก ์ ์ธํ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
- ๊ตณ์ด ๊ตฌํํด๋ณธ๋ค๋ฉด ์ด๋ฐ ํํ๊ฐ ๋๊ฒ ๋ค.
internal func unite0() -> Void {
empty()
}
internal func unite1<T>(_ t: T) -> T {
identity(t)
}
internal func unite2<T, U>(_ t: T, _ u: U) -> (T, U) {
(t, u)
}
internal func unite3<T1, T2, T3>(_ t1: T1, _ t2: T2, _ t3: T3) -> ((T1, T2), T3) {
unite2(unite2(t1, t2), t3)
}
internal func unite4<T1, T2, T3, T4>(_ t1: T1, _ t2: T2, _ t3: T3, _ t4: T4) -> (((T1, T2), T3), T4) {
unite2(unite3(t1, t2, t3), t4)
}
unite_arg
- ๊ทธ๋ผ ์ด์ ๊ฐ์ ํํ์ ํจ์๋ ๋ง๋ค ์ ์์๊น?
unite_arg_3
: ((T1, T2, T3) -> U) -> (((T1, T2), T3) -> U)
internal func uniteArg3<T1, T2, T3, U>(_ f: @escaping ((T1, T2, T3) -> U)) -> (((T1, T2), T3)) -> U {
{ t12_3 in
f(e1(e1(t12_3)), e2(e1(t12_3)), e2(t12_3))
}
}
์ฃผ์ด์ง ํจ์๋ง์ผ๋ก ๊ฐ๋ฅํ๋ค.
reassociate_r
reassociate_r
: ((T, U), V) -> (T, (U, V))
func reassociateR(tl: ((T, U), V))) -> (T, (U, V)) {
unite(e1(e1(tl)), unite(e2(e1(tl)), e2(tl)))
}
reassociate_l
reassociate_l
: (T, (U, V)) -> ((T, U), V)
func reassociateL(tr: (T, (U, V))) -> ((T, U), V) {
unite(unite(e1(tr), e2(e1(tr))), e2(e2(tr)))
}
Monoidal Functor ์ ์
๋ค์์ ๋ง์กฑํ๋ Functor M์ Monoidal Functor๋ผ ํ๋ค. ์ฌ๊ธฐ์ M
์ Monoidal Functor๋ฅผ ์๋ฏธํ๋ค.
pure: T -> M<T>
gather: Tuple(M<T>, M<U>) -> M<Tuple(T, U)>
์ฆ, Functor ์ค์์, lift๊ฐ ์๋ 33. Generic์ค์ ๊ฐ์ 33. Generic์ผ๋ก ํ์ฅํ ์ ์์ผ๋ฉด์
33. Generic์ ํํ์ ํํ์ 33. Generic์ผ๋ก ๋ง๋ค์ด์ค ์ ์๋ ๋ ์์ ๋งํ๋ค. Optional์ ์๋ก ์ฝ๋๋ฅผ ์ฒจ๋ถํด๋ณธ๋ค.
internal func pure<T>(_ value: T) -> Optional<T> {
Optional(value)
}
internal func gather<T, U>(_ tuple: (Optional<T>, Optional<U>)) -> Optional<(T, U)> {
switch tuple {
case (.some(let t), .some(let u)):
return Optional((t, u))
default:
return nil
}
}
Monoidal Functor์ ์กฐ๊ฑด
Conservation of associativity
Conservation of identity element
Monoidal Functor์ ๋ชฉ์
๋ค์ธ์ ํจ์์ ์์ฐ์ค๋ฌ์ด lift๋ฅผ ์ํจ
- ๊ทธ๋ฐ๋ฐ ์์์ functor๋ง ๊ฐ์ง๊ณ ๋ ๋ค์ธ์ ํจ์์ lift๋ฅผ ์ ์ํ ์ ์์ง ์์๋?
lift2d: ((T, U) -> V) -> ((F<T>, F<U>) -> F<F<V>>)
- ํ์ง๋ง ์ธ์ ๋ฐํ ํ์ ์ Generic์ด ์ธ์ ๊ฐ์๋งํผ ๋ค์ด๊ฐ์ ๋์จ๋ค.
lift2: ((T, U) -> V) -> ((M<T>, M<U>) -> M<M<V>>)
- ์ฐ๋ฆฐ ์์ ๊ฐ์ ํํ๋ฅผ ๋ง๋ค๊ณ ์ถ์ ๊ฒ์ด๋ค.
- ํน์
lift0: (() -> U) -> (() -> M<U>)
- ์ด๋ฐ ํํ๋ ์ ์ํด์ ์ฌ์ฉํ๊ณ ์ถ๋ค.
- ์ด๋ฐ ์กฐ๊ฑด์ ์๊ตฌํ๋ค๋ณด๋ ๋์จ๊ฒ Monoidal Functor์ด๋ค.
- Monoidal Functor๊ฐ ์ด๋ป๊ฒ ๋ค์ธ์ ํจ์์ lift๋ฅผ ์ํ๋๋๋ก ๋ง๋ค ์ ์๋์ง ํ์ธํด๋ณด์.
m_unite_{n}
n๊ฐ์ Monoidal functor๋ฅผ ํํ์ ๊ฐ์ผ๋ก ๊ฐ์ง๋ ํํ์ ํ๋์ Monoidal Functor๋ก ๋ง๋๋ ํจ์
m_unite_{n}
(M<T1>, ..., M<T{n}>) -> M<(((T1, T2), T3), ..., T{n})>
m_unite_0 = pure(()) : (() -> M<T>)
m_unite_1(m1) = m1 : (M<T> -> M<T>)
m_unite_n(m1, ..., m{n}) = gather(unite(m_unite_{n-1}(m1, ..., m{n-1}), m{n}))
: (M<T1>, ..., M<T{n}>) -> M<(((T1, T2), T3), ..., T{n})>
- ์์ ๊ฐ์ด ์ฌ๊ท์ ์ผ๋ก ์ ์ํ๋ฉด ๋๋ค.
- ์ด๋ฅผ ํจ์๋ก ๋ฐ๊พธ๋ ๊ฒ์ ์ด๋ ต์ง ์๋ค.
internal func mUnite0() -> Optional<Void> {
pure(empty())
}
internal func mUnite1<T>(_ mt: Optional<T>) -> Optional<T> {
identity(mt)
}
internal func mUnite2<T1, T2>(_ mt1: Optional<T1>,
_ mt2: Optional<T2>) -> Optional<(T1, T2)> {
gather(unite(mt1, mt2))
}
internal func mUnite3<T1, T2, T3>(_ mt1: Optional<T1>,
_ mt2: Optional<T2>,
_ mt3: Optional<T3>) -> Optional<((T1, T2), T3)> {
mUnite2(mUnite2(mt1, mt2), mt3)
}
internal func mUnite4<T1, T2, T3, T4>(_ mt1: Optional<T1>,
_ mt2: Optional<T2>,
_ mt3: Optional<T3>,
_ mt4: Optional<T4>) -> Optional<(((T1, T2), T3), T4)> {
mUnite2(mUnite3(mt1, mt2, mt3), mt4)
// == mUnite2(mUnite2(mUnite2(mt1, mt2), mt3), mt4)
}
์ฆ, ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๊ฐ ํ ์ผ์ ์ฐ๋ฌ์ ๋์จ n๊ฐ์ ๊ฐ์ nestedํ ํ๋์ ํํ๋ก ๋ฌถ์ ๊ฒ์ด๋ค.
lift_n
- ๊ทธ๋ผ
m_unite_n
์ ๊ฐ์ง๊ณlift_n
์ ๋ง๋ค์ด๋ณด์.
lift_n
: ((T1, ..., T{n}) -> U) -> (M<T1>, ..., M<T{n}) -> M<U>
internal func lift3<T1, T2, T3, U>(_ f: @escaping ((T1, T2, T3) -> U)) -> (T1?, T2?, T3?) -> U? {
{ mt1, mt2, mt3 in
lift(uniteArg3(f))(mUnite3(mt1, mt2, mt3))
}
}
- ์ฌ๋ฐ๋ ๊ฑด
lift_n
์ ๊ฐ์ง๊ณm_unite_n
๋ ๋ง๋ค ์ ์๋ค๋ ๊ฒ์ด๋ค.
internal func lift3<T1, T2, T3, U>(_ f: @escaping ((T1, T2, T3) -> U)) -> (T1?, T2?, T3?) -> U? {
{ mt1, mt2, mt3 in
lift(uniteArg3(f))(mUnite3(mt1, mt2, mt3))
}
}
internal func unite3<T1, T2, T3>(_ t1: T1,
_ t2: T2,
_ t3: T3) -> ((T1, T2), T3) {
unite(unite(t1, t2), t3)
}
internal func mUnite3<T1, T2, T3>(_ mt1: T1?,
_ mt2: T2?,
_ mt3: T3?) -> ((T1, T2), T3)? {
mUnite2(mUnite2(mt1, mt2), mt3)
}
internal func mUnite3<T1, T2, T3>(_ mt1: T1?,
_ mt2: T2?,
_ mt3: T3?) -> ((T1, T2), T3)? {
lift3(unite3)(mt1, mt2, mt3)
}
mUnite3 = lift3(unite3)
- ์ด ์๊ธฐ๋
mUnite_n
๊ณผlift_n
์ด ์๋ก๋ฅผ ํตํด ์ ์ํ ์ ์๋ ๋์น ๊ด๊ณ์ ์์์ ์๋ฏธํ๋ค.
pure์ gather
pure
์gather
์ญ์lift
๋ฅผ ์ฌ์ฉํ์ฌ ์ ์ ๊ฐ๋ฅํ๋ค.
internal func pure<T>(_ value: T) -> Optional<T> {
Optional(value)
}
internal func pureFromLift<T>(_ value: T) -> Optional<T> {
lift0 { () -> T in
value
}()
}
internal func gather<T, U>(_ tuple: (Optional<T>, Optional<U>)) -> Optional<(T, U)> {
switch tuple {
case (.some(let t), .some(let u)):
return Optional((t, u))
default:
return nil
}
}
internal func gatherFromLift<T, U>(_ tuple: (Optional<T>, Optional<U>)) -> Optional<(T, U)> {
mUnite2(e1(tuple), e2(tuple))
}
์ ๋ฆฌํด๋ณด์.
- ์๋ 4๊ฐ์ ํจ์๊ฐ ๋์ํ๋ ์ธ์ด์ฌ์ผ Monoidal Functor๋ ์ ์๋๋ค.
enum Summary {
}
extension Summary {
internal func empty() -> Void {
()
}
internal func unite<T, U>(_ t: T, _ u: U) -> (T, U) {
(t, u)
}
internal func e1<T, U>(_ tu: (T, U)) -> T {
tu.0
}
internal func e2<T, U>(_ tu: (T, U)) -> U {
tu.1
}
}
Monoidal Functor๊ฐ ๋๊ธฐ ์ํ ์กฐ๊ฑด, ์๋์ ๋ ํจ์๋ง ์ ์๋๋ฉด ๋๋ค.
extension Summary {
internal func pure<T>(_ t: T) -> T? {
Optional(t)
}
internal func gather<T, U>(_ tuple: (T?, U?)) -> (T, U)? {
switch tuple {
case (.some(let t), .some(let u)):
return Optional((t, u))
default:
return nil
}
}
}
- ์ด์ํฉ์์ ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ถ์๊ฒ ๋ญ๊น?
- ์ฐ๋ฆฌ๊ฐ ํ๊ณ ์ถ์ ๊ฑด ๋ค์ธ์ ํจ์์ lift๋ฅผ ์ ์ ์ํ๋ ๊ฒ์ด๋ค.
- ((T1, T2, T3) โ U)) โ (T1?, T2?, T3?) โ U? ์ด๋ฐ ํํ.
- ๋จผ์ unite_n์ ์ ์ํ์. n๊ฐ์ ๋ํด์๋ ์๋๋ 3๊ฐ๊น์ง๋ง ํด๋ณด์.
extension Summary {
internal func unite0() -> Void {
empty()
}
internal func unite1<T>(_ t: T) -> T {
identity(t)
}
internal func unite2<T1, T2>(_ t1: T1, _ t2: T2) -> (T1, T2) {
(t1, t2)
}
internal func unite3<T1, T2, T3>(_ t1: T1, _ t2: T2, _ t3: T3) -> ((T1, T2), T3) {
unite(unite(t1, t2), t3)
}
}
- ๋ค์์ผ๋ก m_unite_n์ ์ ์ํ์.
extension Summary {
internal func mUnite0() -> Void? {
pure(empty())
}
internal func mUnite1<T>(_ mt: T?) -> T? {
identity(mt)
}
internal func mUnite2<T1, T2>(_ mt1: T1?,
_ mt2: T2?) -> (T1, T2)? {
gather(unite(mt1, mt2))
}
internal func mUnite3<T1, T2, T3>(_ mt1: T1?,
_ mt2: T2?,
_ mt3: T3?) -> ((T1, T2), T3)? {
mUnite2(mUnite2(mt1, mt2), mt3)
}
}
- ๋ง์ง๋ง ํ๋์ ํจ์๋ง ๋ ์ ์ํ์. uniteArg3.
extension Summary {
internal func uniteArg3<T1, T2, T3, U>(_ f: @escaping ((T1, T2, T3) -> U)) -> (((T1, T2), T3)) -> U {
{ t12_3 in
f(e1(e1(t12_3)), e2(e1(t12_3)), e2(t12_3))
}
}
}
- ์ด์ lift ํจ์๋ฅผ ๋ง๋ค์ด๋ณด์.
extension Summary {
internal func lift2<T1, T2, U>(_ f: @escaping ((T1, T2) -> U)) -> (T1?, T2?) -> U? {
{ mt1, mt2 in
lift(f)(mUnite2(mt1, mt2))
}
}
internal func lift3<T1, T2, T3, U>(_ f: @escaping ((T1, T2, T3) -> U)) -> (T1?, T2?, T3?) -> U? {
{ mt1, mt2, mt3 in
lift(uniteArg3(f))(mUnite3(mt1, mt2, mt3))
}
}
}
- ๊ทธ๋ฐ๋ฐ lift3๋ก mUnite3์ ํํํ ์ ์๋ค.
extension Summary {
internal func mUnite2FromLift<T1, T2>(_ mt1: T1?,
_ mt2: T2?) -> (T1, T2)? {
lift2(unite2)(mt1, mt2)
}
internal func mUnite3FromLift<T1, T2, T3>(_ mt1: T1?,
_ mt2: T2?,
_ mt3: T3?) -> ((T1, T2), T3)? {
lift3(unite3)(mt1, mt2, mt3)
}
}
- ๋ญ๊ฐ ์ด์ํ๋ค. lift๋ฅผ ์ฐพ์์จ ์ฌ์ ์ธ๋ฐ, ๊ทธ๊ฒฐ๊ณผ๋ก ์์ ์ ์ ์ํ ์ ์๋ค๋.
- ์ฆ ๋์น์ธ ๊ตฌ์กฐ๋ฅผ ๋ฐ๊ฒฌํ ๊ฒ์ด๋ค.
๋์น ๊ตฌ์กฐ
- ์ด ๋ถ๋ถ์์ ๋งํ์ ์ฌ๋ฌ๊ฐ์ง ์๋๋ฅผ ํด๋ณด์๋ค.
- ๋ง์ง์ ๊ฑฐ๋ ค๋ณด๋ฉด, ํจ์๋ค์ด ์๋ก ์ํํ๋ฉด์ ๋ด๊ฐ ์ ์๋๊ธฐ ์ํด์๋ ๋ค๋ฅธ ํจ์๊ฐ ์๊ตฌ๋๋ ์ํฉ์ด ํผ์ณ์ง๋ค.
enum Veritication {
}
extension Veritication {
// ํ์ ํจ์
internal func lift0<T>(_ transform: @escaping () -> T) -> (() -> T?) {
{ () -> T? in
transform()
}
}
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))
}
}
}
internal func lift2<T1, T2, U>(_ f: @escaping ((T1, T2) -> U)) -> (T1?, T2?) -> U? {
{ mt1, mt2 in
lift(f)(mUnite2(mt1, mt2))
}
}
internal func unite2<T1, T2>(_ t1: T1, _ t2: T2) -> (T1, T2) {
(t1, t2)
}
// ์ฆ๋ช
์์
internal func pure<T>(_ t: T) -> T? {
Optional(t)
}
internal func pureFromLift<T>(_ value: T) -> Optional<T> {
lift0 { () -> T in
value
}()
}
internal func gather<T, U>(_ tuple: (T?, U?)) -> (T, U)? {
switch tuple {
case (.some(let t), .some(let u)):
return Optional((t, u))
default:
return nil
}
}
internal func gatherFromLift<T, U>(_ tuple: (Optional<T>, Optional<U>)) -> Optional<(T, U)> {
// mUnite2(e1(tuple), e2(tuple))
mUnite2FromLift(e1(tuple), e2(tuple))
}
internal func mUnite2<T1, T2>(_ mt1: T1?,
_ mt2: T2?) -> (T1, T2)? {
gather(unite(mt1, mt2))
}
internal func mUnite2FromLift<T1, T2>(_ mt1: T1?,
_ mt2: T2?) -> (T1, T2)? {
lift2(unite2)(mt1, mt2)
}
}
๊ฒฐ๋ก
Monoidal Functor๋ Functor๊ฐ lift_n์ ๊ฐ๊ธฐ ์ํ ํ์์ถฉ๋ถ์กฐ๊ฑด์ด๋ค.
- Monoidal Functor๋
pure
,gather
๋ง ์ ์ํ๋ค. - ๊ทธ๋ฆฌ๊ณ ๊ทธ ์ํฉ์์
lift_n
์ด ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ผด๋ก ์ ์๋๋์ง ํ์ธํด๋ดค๋ค. - ๊ทธ๋ฌ๋๋
lift_n
์ด ์ ์ ์๋์๋ค!
ํน์.
lift_n
์ด ์ ์๋๋ ์กฐ๊ฑด์ ์ฐพ์๋ค.- ๊ทธ๋ด ๊ฒฝ์ฐ
pure
,gather
ํจ์๋ ๋ฌด์กฐ๊ฑด ๋ง์กฑํ๋ค. - ์ฆ, Monoidal Functor๋ ๋ค์ธ์ ํจ์์ lift๋ฅผ ์ํ๋ ๊ผด๋ก ๋ง๋๋ ๋ ์์ด๋ค.
์์ชฝ ๋ชจ๋ ๊ฐ์ ๊ฒฐ๋ก ์ ๋๋ฌํ๊ณ ์๋ค. ์ด ๊ฒฐ๊ณผ๋ฅผ ํตํด Monoidal Functor๊ฐ Functor์ Monad ์ฌ์ด ๋ฒ์ฃผ์ ํด๋นํ๋ ๋ ์์์ ํ์ธํ ์ ์๋ค.
์ ๋ง์ด ์ฌ์ฉ๋์ง ์๋๊ฐ?
- ํจ์ํ ์ธ์ด์์ ๋ค์ธ์ ํจ์์ ์ธ์๋ฅผ ํํ์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ.
- ๋ฐ๋๋ก ๋งํ๋ฉด n-tuple์ ์ ์ง์ํ๋ ์ธ์ด์์๋ ์ด ๊ฐ๋ ์ด ์ฃผ๋ฅ๊ฐ ๋์์ ๊ฒ.
- ํํ๋ง๊ณ ํจ์ํ ์ธ์ด ํ๊ฒฝ์์ ๋ ์ ํ์ฉ๋ ์ ์์ ๋งํ ๊ฐ๋ ์ ๋ฃ์ ์ ์๋๋ฐ,
apply: M<T->U> -> (M<T>->M<U>)
์ด๋ค.- ํด๋น ํจ์๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ๊ณง 10. Applicative Functor์ด๋ค.