์–ด๋–ป๊ฒŒ Monad๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๊ฐ€?

์‚ฌ์šฉ๋ฐฉ๋ฒ•

  1. Monad ํ•จ์ˆ˜๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.
    • flatLift, flatLift2d
  2. ์–ธ์–ด์—์„œ ์ œ๊ณตํ•˜๋Š” Monad ํŠนํ™”๋œ ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
    • do(Haskell), for(Scala)

์ง์ ‘ ์‚ฌ์šฉ

var sum = 0
for i in 1...10 {
    sum += i
}
  • ์ผ๋ฐ˜์ ์ธ ๋ช…๋ นํ˜• ์–ธ์–ด์—์„œ for๋ฌธ์„ ๋„๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.
  • ์šฐ๋ฆฌ๋Š” ์–ด๋– ํ•œ ๋™์ž‘์ด ๋ฐ˜๋ณต๋˜๋ฉด, ์ด๋ฅผ ํ•จ์ˆ˜๋กœ ๋งŒ๋“ค๋ผ๊ณ  ๋ฐฐ์› ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ์›ํ•˜๋Š” ๊ฐ’์„ ๊ฐฑ์‹ ํ•˜๋Š” ๊ฒƒ๋„ ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋กœ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ?
reapply: (Container<T>, U, (U, T) -> U) -> U
  • ์œ„์˜ ๋™์ž‘์„ ๋ถ„์„ํ•˜๋ฉด ์œ„์™€ ๊ฐ™๋‹ค.
  • ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋ฐ›๊ณ , ์ดˆ๊ธฐ ์ƒํƒœ๊ฐ’์„ ๋ฐ›๋Š”๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๋ณ€ํ™˜ํ•จ์ˆ˜๋ฅผ ๋ฐ›์€ ๋’ค, ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฆฌํ„ดํ•œ๋‹ค.
func reapply(_ container: [T], _ initial: U, _ transform: (T, U) -> U) -> U {
    var result = initial
    for element in container {
        result = transform(result, element)
    }
    return result
}
 
reapply([1, 2, 3, 4, 5], 0, {
    $0 + $1
})
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ณ€์ˆ˜, ๋ฐ˜๋ณต๋ฌธ์ด ์—†๋Š” ์ƒํƒœ๋กœ ๊ฐ™์€์ผ์„ ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
  • repeat(Lisp), foldl(Haskell), reduce(Swift) ๋“ฑ์˜ ์ด๋ฆ„์œผ๋กœ ๋ถˆ๋ฆฌ๋Š” ํ•จ์ˆ˜์ด๋‹ค.
  • ๊ณ ์ฐจ ํ•จ์ˆ˜๋“ค์€ ๋‹ค ์ด๋Ÿฐ ํ˜•ํƒœ๋กœ ์žˆ๋‹ค.
  • ๋ณดํ†ต ์‹ค์ œ ํ•จ์ˆ˜๋Š” ์ต๋ช…ํ•จ์ˆ˜๋กœ ๋„˜๊ธฐ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.
let opt: T?
let opu: U?
 
optional.flatLift2d { (t: T, u: U) -> V? in
    // ...
} (opt, opu)
  • flatLift๋„ ์ด์™€ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค.
  • ์ด๋ ‡๊ฒŒ ์จ๋†“์œผ๋‹ˆ, ์Šค์ฝ”ํ”„ ์•ˆ์—๋Š” (T, U) -> V?๋ฅผ ๋ณด๋‚ด๋Š” ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜์—ฌ
  • (T?, U?) -> V?๋กœ ๋ฐ”๊ฟ”์ฃผ๋Š” ์—ฐ์‚ฐ์ด flatLift2d์ž„์„ ์–ด๋ ต์ง€ ์•Š๊ฒŒ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์–ด๋Œ‘ํ„ฐ ์—ญํ• .
let opt: [T] = [3, 7]
let opu: [U] = [2, 4, 8]
 
Array.flatLift2d { (t: T, u: U) -> [V] in
    List.unit { t*10 + u }
} (opt, opu) // [32, 34, 38, 72, 74, 78]
  • ์ด๋Ÿฐ ๋™์ž‘์„ ๋ณดํ†ต ์–ธ์–ด์—์„œ flatMap๊ณผ ๊ฐ™์€ ๋ณ€์ข…์„ ์ œ๊ณตํ•œ๋‹ค.

Monad ํŠนํ™”๋œ ์–ธ์–ด์˜ ๊ฒฝ์šฐ

do {
    t <- opt
    u <- opu
    f(t, u)
}
  • Haskell์˜ ๊ฒฝ์šฐ do๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋ชจ์–‘์ด ํก์‚ฌํ•จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋Ÿฐ ๋ฌธ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๋‹ค์ด๋‹ค.
integra {
    y <- [0, 1]
    x <- [0, y]
    pow(x, y)
}
  • ์ด๋ ‡๊ฒŒ ๋‹ค์ค‘ ์ ๋ถ„๋„ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„๊ฐ€๋Šฅํ•˜๋‹ค.
do {
    t <- opt
    unit(true)
}
  • ๊ทธ๋Ÿผ ์ด๊ฑด ๋ญ˜๊นŒ?
  • ์•„๋ž˜ ๋ณ€ํ™˜ ํ•จ์ˆ˜๋Š” t์— ๋Œ€ํ•œ ํ•จ์ˆ˜๊ฐ€ ์•„๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ opt๊ฐ€ ๋นˆ ๊ฐ’์ด๋ผ๋ฉด, ๊ฒฐ๊ณผ๋Š” ๋นˆ ๊ฐ’์œผ๋กœ ๋‚˜์˜ฌ ๊ฒƒ์ด๋‹ค.
  • ๊ฐ’์ด ์žˆ๋‹ค๋ฉด true๊ฐ€ ๋‹ด๊ธด Optional์ด ๋‚˜์˜ฌ ๊ฒƒ์ด๋‹ค.
  • ์‚ฌ์šฉํ•˜์ง€๋„ ์•Š๋Š” ๊ฐ’์„ ๋„ฃ์–ด, true๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, ์—†๋Š” ๊ฒฝ์šฐ๋กœ ๋ฐ”๊ฟ”์„œ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค.
  • ์ด๋Ÿฐ ๊ฒƒ๋„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.

Reference