일부 언어는 유형 매개 변수가있는 클래스 및 함수 (예 : 임의 유형일 수있는 List<T>
위치 T
)를 허용합니다. 예를 들어 다음과 같은 기능을 가질 수 있습니다.
List<S> Function<S, T>(List<T> list)
그러나 일부 언어에서는이 개념을 한 단계 위로 확장하여 서명 기능을 가질 수 있습니다.
K<S> Function<K<_>, S, T>(K<T> arg)
어디 K<_>
그 자체 것은 같은 유형의 List<_>
그 유형 매개 변수가 있습니다. 이 “부분 유형”은 유형 생성자로 알려져 있습니다.
제 질문은 왜이 능력이 필요한가요? List<T>
모든 List<T>
것이 거의 동일 하기 때문에 같은 유형을 갖는 것이 합리적 이지만 모든 K<_>
것은 완전히 다를 수 있습니다. 당신은 할 수 있습니다 Option<_>
와 List<_>
전혀 공통 기능이없는 것을.
답변
그 누구도 그 질문에 대답하지 않았기 때문에, 나는 그것을 스스로에게 줄 것이라고 생각합니다. 나는 약간의 철학을 얻어야 할 것이다.
일반 프로그래밍은 유형 정보의 손실없이 객체 유형 값 다형성에서 발생하는 유사한 유형에 대한 추상화에 관한 것입니다. 이를 위해서는 유형이 반드시 사용할 수있는 일종의 인터페이스 (OO 용어가 아닌 일련의 작업)를 공유해야합니다.
객체 지향 언어에서 유형은 클래스 덕분에 인터페이스를 충족시킵니다. 각 클래스에는 유형의 일부로 정의 된 자체 인터페이스가 있습니다. 모든 클래스 List<T>
는 동일한 인터페이스를 공유 하므로 T
선택한 코드에 관계없이 작동하는 코드를 작성할 수 있습니다. 인터페이스를 적용하는 또 다른 방법은 상속 제약 조건이며, 두 가지가 다르게 보이지만 생각하면 비슷합니다.
대부분의 객체 지향 언어에서 List<>
적절한 유형이 아닙니다. 메소드가 없으므로 인터페이스가 없습니다. List<T>
이것들 만이 있습니다. 본질적으로,보다 기술적 인 용어로, 의미있게 추상화 할 수있는 유일한 유형은 종류가있는 유형 *
입니다. 객체 지향 세계에서 더 높은 종류의 유형을 사용하려면이 제한과 일치하는 방식으로 유형 제약 조건을 표현해야합니다.
예를 들어, 주석에서 언급 한 바와 같이, 우리는 볼 수 있습니다 Option<>
그리고 List<>
당신은 기능이있는 경우 “맵핑이”와 같은 의미에서, 당신은 변환 할 수 있음을 Option<T>
에 Option<S>
, 또는를 List<T>
로 List<S>
. 클래스를 사용하여보다 높은 유형의 유형을 직접 추상화 할 수는 없다는 점을 기억하고 대신 인터페이스를 만듭니다.
IMappable<K<_>, T> where K<T> : IMappable<K<_>, T>
그런 다음 인터페이스를 각각 List<T>
및 Option<T>
as IMappable<List<_>, T>
및 as로 구현합니다 IMappable<Option<_>, T>
. 우리가 한 일은 더 높은 종류의 유형을 사용하여 실제 (높은 종류가 아닌) 유형 Option<T>
과에 제한을 두는 것 List<T>
입니다. 물론 Scala는 특성, 유형 변수 및 암시 적 매개 변수와 같은 기능을 통해보다 표현력을 향상시킬 수 있습니다.
다른 언어에서는 더 높은 종류의 유형을 직접 추상화 할 수 있습니다. 유형 시스템의 최고 권한 중 하나 인 Haskell에서는 유형이 더 높더라도 모든 유형에 대한 유형 클래스를 문구화할 수 있습니다. 예를 들어
class Mappable mp where
map :: mp a -> mp b
이것은 mp
하나의 유형 매개 변수를 취하는 (지정되지 않은) 유형에 직접 배치되는 제약 조건 map
이며 mp<a>
로 변환하는 함수와 관련되어야 합니다 mp<b>
. 그런 다음 Mappable
상속 제한을 적용 할 수있는 객체 지향 언어와 같이 더 높은 종류의 유형을 제한하는 함수를 작성할 수 있습니다 . 글쎄요.
요약하면, 상위 유형의 유형을 사용하는 능력은 유형을 제한하거나 유형 제약 조건의 일부로 사용하는 능력에 달려 있습니다.