박스형이 아닌 유형에 비해 높은 순위의 다형성


10

Hindley–Milner를 기반으로 유형 유추를 사용하여 기본적으로 유형이 상자 해제 된 언어가 있습니다. 주로 실존 유형으로 작업하기 위해 더 높은 순위의 다형성을 추가하고 싶습니다.

이러한 유형 을 확인 하는 방법을 이해 하고 있지만 컴파일 할 때 무엇을 해야할지 잘 모르겠습니다. 현재 저는 C ++ 템플릿과 같이 전문화를 생성하여 다형성 정의를 컴파일하여 unboxed 값으로 작업 할 수 있습니다. 예를 들어의 정의 f<T>에서 프로그램이 f<Int32>및 만 호출하면 f<Char>해당 전문화 만 컴파일 된 프로그램에 나타납니다. (현재 전체 프로그램 컴파일을 가정하고 있습니다.)

그러나 다형성 함수를 인수로 전달할 때 런타임에 함수를 선택할 수 있기 때문에 올바른 특수화를 정적으로 생성하는 방법을 알 수 없습니다. 박스형 표현을 사용하는 것 외에는 선택의 여지가 있습니까? 아니면 문제를 해결할 방법이 있습니까?

내 첫 번째 생각은 어떻게 든 순위 n 다형성을 순위 1로 인코딩하는 것이었지만 건설 논리의 수식이 반드시 프리 넥스 정규 형식을 가질 필요는 없기 때문에 일반적으로 가능하다고는 생각하지 않습니다.


대안은 함수의 인수와 메모리의 단어가 포인터 인 비트 맵을 저장하여 필요한 권투 량을 줄이는 것입니다. 그런 다음 다형성 함수 / 구조체는 실제로 포인터 또는 임의의 데이터 단어에 대해 다형성 이며 구조체는 마지막 필드 (다형성 일지라도)를 인라인으로 저장할 수 있습니다. 이러한 비트 맵은 GC에서 비 합계 유형에 대한 태그 워드가 필요하지 않도록 사용할 수도 있습니다.
fread2281

@ fread2281 : 실제로 이전 버전의 언어에서 이와 비슷한 작업을 수행했습니다. 현재 비 합계 유형에 대한 태그를 생성하지 않으며 GC가 없습니다. 나는 이것이 Neel K의 접근 방식과도 호환된다고 생각합니다.
Jon Purdy

답변:


6

나는 이것에 대해 조금 생각했습니다. 주요 문제는 일반적으로 다형성 유형의 값이 얼마나 큰지 모른다는 것입니다. 이 정보가 없으면 어떻게 든 정보를 얻어야합니다. 단형 화는 다형성을 전문화하여이 정보를 제공합니다. 권투는 알려진 크기의 표현으로 모든 것을 넣어서 당신을 위해이 정보를 얻습니다.

세 번째 대안은 이러한 정보를 종류별로 추적하는 것입니다. 기본적으로 수행 할 수있는 작업은 각 데이터 크기마다 다른 종류를 도입 한 다음 특정 크기의 모든 유형에 대해 다형성 함수를 정의 할 수 있습니다. 아래에 그러한 시스템을 스케치하겠습니다.

종류κ:: =타입 생성자:: =:κ.|α|×|+||아르 자형이자형에프|(케이)|μα:κ.

여기서 높은 수준의 아이디어는 유형의 종류가 메모리에 객체를 배치하는 데 얼마나 많은 단어가 필요한지 알려줍니다. 특정 크기의 경우 특정 크기의 모든 유형에 대해 다형성이 쉽습니다. 모든 유형 (다형성 유형까지도)은 여전히 ​​알려진 크기를 가지므로 컴파일은 C보다 어렵지 않습니다.

분류 규칙은이 영어를 수학으로 바꾸며 다음과 같이 표시됩니다.

α:ΓΓα:Γ,α::미디엄Γα:.:미디엄
Γ:Γ:미디엄Γ×:+미디엄Γ:Γ:Γ+:+1
Γ:미디엄Γ:Γ:1Γ:Γ아르 자형이자형에프:1
Γ(케이):케이Γ,α::Γμα:.:

따라서 모든 정량자는 당신이 원하는 종류를 제공해야합니다. 마찬가지로, 페어링 것은 언 박스형 (unboxed pair) 타입으로, 메모리 에서 옆에 (C 구조체 타입과 같은)를 배치합니다. 분리 결합은 같은 크기의 두 값을 취한 다음 판별 기 태그에 대한 단어를 추가합니다. 함수는 일반적으로 환경 레코드와 코드에 대한 포인터로 표시되는 클로저입니다.×

참조는 흥미 롭습니다. 포인터는 항상 한 단어이지만 모든 크기의 값을 가리킬 수 있습니다. 이를 통해 프로그래머 는 복싱을 통해 임의의 객체에 다형성을 구현할 수 있지만 그렇게하지 않아도 됩니다. 마지막으로, 명시적인 크기가 재생되면 공간을 사용하지만 아무것도하지 않는 패딩 유형을 도입하는 것이 종종 유용합니다. (따라서 int와 한 쌍의 int를 결합하지 않으려면 첫 번째 int를 패딩을 추가하여 객체 레이아웃이 균일해야합니다.)

재귀 유형에는 표준 구성 규칙이 있지만 재귀 발생은 크기가 같아야합니다. 즉, 일반적으로 친절한 작업을 수행하려면 포인터에 고정해야합니다. 예를 들어 목록 데이터 유형은

μα:1.아르 자형이자형에프((2)+나는×α)

따라서 이것은 빈 목록 값 또는 int 쌍과 다른 연결된 목록에 대한 포인터를 가리 킵니다.

이와 같은 시스템에 대한 유형 검사도 그리 어렵지 않습니다. 더 높은 순위 다형성에 대한 완전하고 쉬운 양방향 유형 검사 기능을 갖춘 Joshua Dunfield와의 ICFP 논문의 알고리즘은 거의 변함없이이 경우에 적용됩니다.


쿨, 나는 이것이 나의 유스 케이스를 깔끔하게 커버한다고 생각합니다. 나는 가치 표현에 대해 추론하기 위해 종류를 사용하는 것을 알고 있었지만 (GHC *와 비교 #) 이런 식으로 생각하지 않았습니다. 높은 순위의 수량자를 알려진 크기의 유형으로 제한하는 것이 합리적이며 실제 유형을 알 필요없이 크기별 전문화를 정적으로 생성 할 수 있다고 생각합니다. 이제 그 신문을 다시 읽을 차례입니다. :)
Jon Purdy 2012

1

이것은 "이론적 컴퓨터 과학"문제보다 컴파일 문제에 더 가까운 것 같으므로 다른 곳에서 물어 보는 것이 좋습니다.

일반적으로 박스형 표현을 사용하는 것 외에 다른 해결책은 없다고 생각합니다. 그러나 실제로는 상황에 따라 다른 대안이 많이있을 것으로 기대합니다.

예를 들어, 언 박싱 된 인수의 저수준 표현은 일반적으로 정수 또는 유사, 부동 소수점 또는 포인터와 같은 매우 적은 대안으로 분류 될 수 있습니다. 따라서 함수의 f<T>경우 실제로 3 개의 다른 unboxed 구현을 생성해야하며 다형성을 3 개의 함수의 튜플로 나타낼 수 있으므로 T를 Int32로 인스턴스화하는 것은 튜플의 첫 번째 요소를 선택하는 것입니다 ...


당신의 도움을 주셔서 감사합니다. 컴파일러는 고급 이론에서 저수준 엔지니어링에 이르기까지 어디에서 물어볼 지 확실하지 않았지만, 주변 사람들이 아이디어를 가질 것이라고 생각했습니다. 권투가 실제로 가장 유연한 접근법 인 것처럼 보입니다. 답을 읽고 더 많이 생각한 후에, 내가 생각해 낼 수있는 유일한 합리적인 해결책은 유연성을 포기하고 다형성 인수를 정적으로 알려야합니다 (예 : 유형 매개 변수 자체로 전달). 절충점입니다. : P
Jon Purdy 2012

4
OP의 질문에는 Damas-Hindley-Milner가 더 높은 순위 유형으로 확장 될 때 유형 유추를 수행하는 방법과 같이 완벽하게 유효한 TCS 문제가 포함되어 있습니다. 일반적으로 순위 -2 다형성은 결정 가능한 유형 유추를 갖지만 순위 k> 2에 대한 유형 유추는 결정할 수 없습니다. Damas-Hindley-Milner 제한이이를 변경하는지 여부는 모르겠습니다. 마지막으로 현대 컴파일러가하는 거의 모든 것이 TCS의 일부가되어야하지만, 일반적으로 컴파일러 구현자가 이론가보다 앞서 있기 때문은 아닙니다.
Martin Berger
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.