의존 함수 타입

의존 함수 타입 (Dependent Function Types)

의존 함수 타입은 결과 타입이 함수의 파라미터에 의존하는 함수 타입이에요. 말로만 들으면 생소한데, 코드로 보면 금방 이해돼요:

trait Entry { type Key; val key: Key }

def extractKey(e: Entry): e.Key = e.key          // a dependent method

val extractor: (e: Entry) => e.Key = extractKey  // a dependent function value
//             ^^^^^^^^^^^^^^^^^^^
//             a dependent function type

출처: Scala 3 Reference

본문

Scala에는 이미 **의존 메서드(dependent method)**가 있었어요. 메서드의 결과 타입이 메서드의 어떤 파라미터를 가리키는 메서드를 말하죠. extractKey 메서드가 그 예시예요. 이 메서드의 결과 타입 e.Key는 파라미터 e를 가리키고 있어요(이를 'e.Keye에 의존한다'고도 말해요). 그런데 지금까지는 이런 메서드를 함수 값(function value)으로 바꿀 수 없었어요. 다른 함수에 파라미터로 넘기거나 결과로 반환할 수 없었던 거죠. 의존 메서드를 함수로 바꾸지 못했던 단순한 이유는, 그런 메서드를 기술할 수 있는 타입이 없었기 때문이에요.

Scala 3에서는 이제 이게 가능해졌어요. 위 extractor 값의 타입은 이렇게 생겼죠:

(e: Entry) => e.Key

이 타입은 "타입 Entry의 어떤 인자 e를 받아서 타입 e.Key의 결과를 돌려주는 함수 값"을 설명해요.

잠깐, 일반 함수 타입을 떠올려 볼게요. 일반 함수 타입 A => BFunction1 트레이트의 인스턴스(즉 Function1[A, B])로 표현되고, 파라미터가 더 많은 함수도 비슷하게 표현되죠. 의존 함수도 이 트레이트들의 인스턴스로 표현되긴 하지만, 추가로 refinement가 붙어요. 실제로 위 의존 함수 타입은 아래처럼 쓰는 것의 문법적 설탕(syntactic sugar)이에요:

Function1[Entry, Entry#Key]:
  def apply(e: Entry): e.Key