Skip to content

Instantly share code, notes, and snippets.

@nattybear
Last active December 30, 2020 17:00
Show Gist options
  • Save nattybear/387d22fc82c7339a29e0c93084fef10e to your computer and use it in GitHub Desktop.
Save nattybear/387d22fc82c7339a29e0c93084fef10e to your computer and use it in GitHub Desktop.
하스켈 Continuation Passing Style, CPS

이 글은 위키북스 하스켈을 읽고 정리한 것이다.

함수와 값의 표현

명령형 프로그래밍에서는 보통 아래와 같이 표현한다.

함수에 값을 넣는다.

그런데 하스켈에서는 아래와 같이 표현한다.

값에 함수를 적용한다. apply function to value

continuation이 뭐야?

보통은 아래처럼 값에 함수를 적용하곤 한다.

GHCi> map (*2) [2, 4, 8]
[4,8,16]

그런데 아래처럼 할 수도 있다.

GHCi> map ($ 2) [(2*), (4*), (8*)]
[4,8,16]

이때 ($ 2) 같은 것을 '잠시 멈춘 계산'이라고 한다. suspended computation

타입으로 표현하면 아래와 같다.

(a -> r) -> r

이 잠시 멈춘 계산 ($ 2)

  • (2*)라는 함수를 넣어주면 (a -> r)
  • 4라는 결과가 나오는 것이다! r

(2*) :: a -> r과 같은 것을 continuation이라고 한다.

suspended computation을 continuation에 '던진다'고 표현하는 것 같다. throw

이러한 방식을 CPS라고 한다. Continuation Passing Style

flip ($)을 이용하면 아무 값이나 suspended computation으로 만들 수 있고 여기에 함수 id를 continuation으로 넣으면 원래 값이 나온다.

flip     :: (a -> b -> c) -> b -> a -> c
($)      :: (a -> b) -> a -> b
flip ($) :: a -> (a -> r) -> r
flip ($) x id == x

이걸 어따 쓰나?

CPS를 이용하면 하스켈 초보자를 골탕 먹일 수 있다 아래와 같은 것들이 가능하다.

  • 예외 처리하기
  • concurrency 구현하기

아직 겪어보거나 구현해본 적이 없어서 구체적으로 적지는 못하겠다.

위키백과에 따르면 컴파일러에서 많이 사용한다고 한다.

피타고라스

아래와 같이 보통 스타일의 함수가 있다고 하자.

add :: Int -> Int -> Int
add x y = x + y

square :: Int -> Int
square x = x * x

pythagoras :: Int -> Int -> Int
pythagoras x y = add (square x) (square y)

위 함수들을 아래와 같이 suspended computation을 리턴하는 방식으로 바꿔보자. (a -> r) -> r

add_cps :: Int -> Int -> ((Int -> r) -> r)
add_cps x y = \k -> k (add x y)

square_cps :: Int -> ((Int -> r) -> r)
square_cps x = \k -> k (square x)

pythagoras_cps :: Int -> Int -> ((Int -> r) -> r)
pythagoras_cps x y = \k ->
  square_cps x $ \x_squared ->
  square_cps y $ \y_squared ->
  add_cps x_squared y_squared $ k
  • suspended computation ($ 2)를 continuation (2*)에 던진다.
  • suspended computation square_cps x를 continuation \x_squared -> ...에 던진다.
  • suspended computation square_cps y를 continuation \y_squared -> ...에 던진다.

아래처럼 사용할 수 있다.

GHCi> pythagoras_cps 3 4 print
25

대문 링크

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment