언어 설계, HM vs 양방향 타입 시스템, 무엇을 선택해야 할까?
언어 설계 시 HM 타입 시스템(Hindley-Milner Type System)과 양방향 타입 시스템(Bidirectional Typing) 중 어떤 것을 선택할지 고민하는 것은 잘못된 질문임
핵심은 제네릭(Generics) 지원 여부이며, 제네릭을 지원하려면 통합(Unification)이 필요함
양방향 타입 시스템은 HM 타입 시스템의 상위 집합(Superset)으로, 통합을 포함하여 더 많은 기능을 제공함
도메인 특화 언어(DSL) 설계 시 제네릭을 배제하고 양방향 타입 시스템을 활용하여 복잡성을 줄일 수 있음
HM과 양방향 타입 시스템의 관계
HM 타입 시스템은 통합(Unification)을 중심으로 설계되며, 타입 변수를 추론하는 데 중점을 둔다. 반면, 양방향 타입 시스템은 주석(Annotation)을 통해 타입을 결정하며, 통합 없이도 복잡한 프로그램을 타입 검사할 수 있다. 기술적으로 보면, 양방향 타입 검사는 HM의 상위 집합이므로 HM의 모든 기능을 지원하며, 통합을 포함하여 더 유연한 설계를 가능하게 한다. 특히, 양방향 타입 검사(Bidirectional Typechecking)는 HM보다 더 많은 기능을 제공하며, 언어 설계 시 다양한 선택지를 제공한다.
제네릭 지원과 통합의 필요성
제네릭을 지원하려면 통합(Unification)이 필수적이다. 통합은 타입 변수를 할당하고 해결하는 과정으로, Rust와 같은 언어에서 타입 추론을 가능하게 한다. 언어 설계자는 제네릭 지원 여부에 따라 HM 또는 양방향 타입 시스템을 선택할 수 있다. 제네릭은 코드의 재사용성을 높이지만, 타입 시스템의 복잡성(Complexity)을 증가시키므로, 언어의 목적에 따라 신중하게 결정해야 한다.
양방향 타입 시스템의 장점
양방향 타입 시스템은 HM 타입 시스템에 비해 유연성이 높다. HM 타입 시스템(Hindley-Milner Type System)에 몇 줄의 코드를 추가하여 양방향 시스템으로 만들 수 있으며, 이는 언어 설계자에게 추가적인 기능을 제공한다. 특히, 함수형 언어(Functional Language) 설계 시 양방향 타입 시스템은 타입 추론(Type Inference)과 타입 검사(Type Checking)를 효율적으로 수행할 수 있도록 돕는다. 또한, 코드 가독성(Code Readability)을 높이는 데 기여한다.
DSL 설계에서의 양방향 타입 시스템 활용
도메인 특화 언어(DSL) 설계 시 제네릭을 배제하고 양방향 타입 시스템을 활용하면 언어의 복잡성(Complexity)을 줄일 수 있다. DSL은 특정 도메인에 특화되어 있어, 모든 기능을 지원할 필요가 없기 때문이다. 제네릭(Generics)을 제거하면 언어의 표현력(Expressiveness)은 감소하지만, 학습 곡선(Learning Curve)을 완만하게 만들 수 있다. 하지만, DSL이 일반적인 프로그래밍 언어로 발전할 가능성을 고려하여, 확장성(Extensibility)을 염두에 두어야 한다.