일단 Continuation Monad에 대해 되게 잘 설명한 글을 찾았는데
이거다
그리고 내가 왜 Continuation Monad를 구현하고 앉아 있냐...하면 KAIST의 프로그래밍 언어론(CS320)을 독학하고 있었는데 거기서 Continuation Passing Style이 나오고, 처음 봤을 땐 잘 이해가 안 돼서 포기하고 있었다. 근데 이젠 어느 정도 이해함
바로 코드를 보자
private class Cont[R, U](data: (U => R) => R) {
def applyCont(f: U => R): R = data(f)
def map[U2](fn: U => U2): Cont[R, U2] = Cont(
(f: U2 => R) => applyCont(fn.andThen(f))
)
def flatMap[U2](fn: U => Cont[R, U2]): Cont[R, U2] = Cont(
(f: U2 => R) => applyCont(u => fn(u).applyCont(f))
)
}
def toCont[R, U](u: U): Cont[R, U] = Cont((f: U => R) => f(u))
def addCPS(a: Int, b: Int): Cont[Int, Int] = toCont(a + b)
def subCPS(a: Int, b: Int): Cont[Int, Int] = toCont(a - b)
def mulCPS(a: Int, b: Int): Cont[Int, Int] = toCont(a * b)
@main
def main(): Unit = {
val ret = for {
v1 <- addCPS(1, 2)
v2 <- subCPS(7, 4)
v3 <- mulCPS(v1, v2)
} yield v3
println(ret.applyCont(x => x))
}
위 링크 달아둔 글을 거의 그대로 구현했다.
먼저 Cont[R, U] 타입은 (U => R) => R 타입을 의미함
일반 함수를 f: T => U라고 하고, continuation을 U => R이라고 하면, Cont[R, U] 타입은 continuation 하나를 받아서 그 continuation의 리턴값을 리턴하는 함수겠죠
즉 continuation이 cont: U => R이라고 하면 Cont[R, U] 타입은 cont 함수의 인자가 될 u를 미리 들고 있습니다 그리고 임의의 continuation인 cont가 인자로 들어오면 cont(u)를 계산해서 리턴합니다
이제 모나딕함을 구현하기 위해 map 함수와 flatMap 함수만 구현해주면 되는데요
map은 쉽습니다 임의의 f: U => U2 함수를 Cont[R, U] => Cont[R, U2] 함수로 바꿔 주기만 하면 되죠
근데 Cont[R, U] 타입이 cont 함수의 인자가 될 u를 미리 들고 있다고 했으므로 Cont[R, U2] 타입은 f(u)를 들고 있으면 될 것 같음
flatMap은 임의의 f: U => Cont[R, U2] 함수를 Cont[R, U] => Cont[R, U2] 함수로 바꿔 주면 되겠죠
map을 먼저 한 뒤에 unit을 해 주는 방식으로 처리합시다
모든 Cont[R, X] 타입은 X 타입으로 생각해줄 수 있겠죠 왜냐하면 내부에 x를 들고 있으므로
'Computer Science' 카테고리의 다른 글
흑 (0) | 2023.12.12 |
---|---|
Bomb Lab에 꼭 필요한 gdb 커맨드 모음 (0) | 2023.10.08 |
Heap과 Priority Queue의 차이, 그리고 Abstract Data Type이란 무엇인가 (0) | 2023.02.07 |
파이썬 튜플에 대한 충격적인 사실 (0) | 2023.01.14 |
고속 푸리에 변환, 이론부터 구현까지 (4) | 2023.01.02 |
댓글