E183: Closure Cannot Have Internal Parameter Dependencies — 클로저는 내부 파라미터 의존성을 가질 수 없음

E183: Closure Cannot Have Internal Parameter Dependencies — 클로저는 내부 파라미터 의존성을 가질 수 없음

한 파라미터의 타입이 같은 파라미터 목록의 다른 파라미터에 의존하는 클로저(익명 함수)를 만들려 할 때 발생하는 에러예요. 이를 "파라미터 의존성(parameter dependency)"이라고 부르며, 클로저에서는 지원되지 않아요.

출처: Scala 3 Reference

본문

Scala에서 클로저는 Function1, Function2 같은 함수 타입으로 변환돼요. 이런 표준 함수 타입은 파라미터 타입이 다른 파라미터를 .type(싱글턴 타입)으로 참조하는 의존적 파라미터 타입(dependent parameter type)을 표현할 수 없어요.

이 제한은 다형 클로저(타입 파라미터가 있는 [T] 형태)와 단형(monomorphic) 클로저 모두에 적용돼요.

예시 (Example)

def example = [T] => (x: T, y: List[x.type]) => List(y)

여기서 파라미터 y의 타입이 List[x.type]인데, 이것은 파라미터 x의 값에 의존해요. 같은 목록 안의 파라미터들 사이의 이런 내부 의존성 때문에 이 클로저를 표준 함수 타입으로 표현할 수 없어요.

에러 (Error)

-- [E183] Type Error: example.scala:1:18 ---------------------------------------
1 |def example = [T] => (x: T, y: List[x.type]) => List(y)
  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |cannot turn method type [T](x: T, y: List[(x : T)]): List[List[(x : T)]] into closure
  |because it has internal parameter dependencies

해결 방법 (Solution)

이 제한을 우회하는 흔한 방법은 두 가지예요:

1. 클로저 대신 일반 메서드 사용하기

클로저를 이름 있는 메서드 정의로 바꾸세요:

def example[T](x: T, y: List[x.type]): List[List[x.type]] = List(y)

2. 커리된 파라미터 사용하기

의존적인 파라미터들을 서로 다른 파라미터 목록으로 나누세요. 그러면 의존하는 파라미터가 앞 목록의 파라미터를 참조할 수 있어요:

def curriedExample = [T] => (x: T) => (y: List[x.type]) => List(y)

이렇게 하면 각 파라미터 목록이 별개의 클로저를 만들어내고, 내부 클로저는 파라미터 간 의존성이 아니라 둘러싼 스코프에서 x를 캡처하기 때문에 동작해요.

더 알아보기

파라미터 타입이 다른 파라미터에 의존하면 클로저(익명 함수)로는 표현할 수 없어요. 명명된 메서드나 커링으로 우회하면 돼요.