2017-05-10 4 views
2

나는 Rust가 Hindley-Milner를 사용하여 매우 좋은 유추 추론을했다고 읽었습니다. Rust는 또한 변이 변수를 가지며 AFAIK는 HM 알고리즘이 지나치게 일반화 될 수 있기 때문에 가변성으로 작동 할 때 몇 가지 제약이 있어야합니다. 다음 코드 : Rust는 Hindley-Milner의 변경 가능성을 어떻게 해결합니까?

let mut a; 
a = 3; 
a = 2.5; 

때문에 두 번째 행의 정수로, 컴파일되지 않습니다는 추정했다 및 부동 소수점 값은 정수 변수에 할당 할 수 없습니다. 그래서 나는 단순한 변수에 대해서는 비 제네릭 타입이 유추 되 자마자 변수가 모노 타입이되어 더 이상 일반화 될 수 없다고 추측합니다.

하지만 Vec과 같은 템플릿은 무엇입니까? 예를 들면 다음과 같습니다.

let mut v; 
v = Vec::new(); 
v.push(3); 
v.push(2.3); 

이 오류는 다시 실패하지만 마지막 행은 다시 실패합니다. 즉, 두 번째 행은 유형을 부분적으로 추론하고 (Vec) 세 번째 행은 컨테이너 유형을 유추했습니다.

어떤 규칙이 적용됩니까? 내가 알지도 못하는 가치 제한 같은 것이 있습니까? 아니면 나는 과잉 복잡하고 녹이 훨씬 엄격한 규칙을 가졌습니까 (전혀 일반화하지 않은 것처럼)? 내가 잘못 아니에요 경우

+2

Rust 유형 추론을 검토하는 작업이 계속 진행 중입니다. Niko Matsakis는 새로운 통합 엔진에 대한 작업을 블로그에 올렸습니다. [통합 분필 - 1 부] (http://smallcultfollowing.com/ babysteps/blog/2017/03/25/통일 - 분필 - 파트 -1 /)과 [분필의 통일 - 제 2 부] (http://smallcultfollowing.com/babysteps/blog/2017/04/23/unification - 초크 - 파트 - 2 /). –

+0

@MatthieuM. 고마워, 내가 이것을 읽을거야! –

답변

2

rustc는 형식 유추에 약간의 열망이있는 것으로 간주됩니다 (진단 품질이 향상되는 한). 우리가 첫 번째 예를 선택하면

는 :

let mut a = 3; 
a = 2.5; 

을 다음 첫 번째 줄은 a{generic integer type}을 가지고 추론에 이르게하고 두 번째 줄은이 아니기 때문에 2.5a에 할당 할 수 없다는 진단 이어질 것 일반 정수 유형.

더 나은 알고리즘이 대신 충돌을 등록한 다음 각 유형이 나온 행을 가리킬 것으로 예상됩니다. 어쩌면 우리는 Chalk으로 그것을 얻을 것입니다.

참고 : 일반 정수 유형은 정수 리터럴을 "다형성"으로 만드는 트릭입니다. 특정 정수 유형에 대한 다른 힌트가 없으면 기본값은 i32입니다.


번째 예는 기본적으로 동일한 방식으로 발생한다.세부

let mut v = Vec::new(); 
v.push(3); 

:

  • v이 할당 유형 $T
  • Vec::new() 우리가 얻을 Vec<$U>
  • 3가 첫 번째 줄에, 그래서 {integer}

을 입력 생산 입력 생산 $T == Vec<$U>이고 두 번째 줄에는 $U == {integer}이 있으므로 vVec<{integer}>으로 추론됩니다.

정확한 정수 유형을 알 수있는 다른 출처가없는 경우 기본값으로 i32으로 되돌아갑니다.


여기서 mutability는 실제로 여기의 추론에 영향을주지 않습니다. 타입 추론, 또는 형식 통일의 관점에서, 다음 코드 샘플은 동일

// With mutability: 
let mut a = 1; 
a = 2.5; 

// Without mutability: 
let a = if <condition> { 1 } else { 2.5 }; 

는 HM, Deref 관련 및 하위 입력만큼 더 도전 올 녹에 훨씬 더 문제가 있습니다.

4

그것은이 수행 다음 VEC 조각에 대한

let mut a; 
a = 3;  //here a is already infered as mut int 
a = 2.5; //fails because int != float 

:

let mut v; 
v = Vec::new();// now v type is Vec<something> 
v.push(3);  // v type is Vec<int> 
v.push(2.3); // here fails because Vec<int> != Vec<float> 

공지 사항 I 녹 유형을 사용하지만, 단지 일반적으로 생각하는 데에 대한 않았다.

+0

알고리즘에 일반화가 없어야한다는 말입니까? –

+0

@ PeterLenkefi, 첫 번째 전문화 된 완전한 유형을 찾을 때까지 일반화됩니다. – Netwave

+1

@PeterLenkefi "일반화 안함"이란 무엇을 의미합니까? 'v = Vec :: new()'는 사실상 일부'T'에 대해'v : Vec '; 'v.push (3)'은'T = {integer}'(이는 그렇지 않다면 증명이 없을 때 디폴트는'i32')의 제약 조건입니다. 어떻게 그러한 제약 조건들이 더 일반화 될 수 있습니까? – trentcl