2012-10-28 2 views
1

내가 이해하지 못하는 Array.map2로 어떤 문제가 발생했습니다. Array.map2 형식의 레코드 추론

이 코드를 고려

type r1 = { 
    v1 : int 
    X : int 
} 

type r2 = { 
    v1 : int 
    Y : int 
} 

let a1 = [|{v1=1; X=1}; {v1=2; X=2}|] // val a1 : r1 [] ... 
let a2 = [|{v1=100; Y=100}; {v1=200; Y=200}|] // val a2 : r2 [] ... 

Array.map2 (fun x1 x2 -> (x1.X, x2.Y)) a1 a2 // works as expected 
Array.map2 (fun x1 x2 -> (x1.v1, x2.v1)) a1 a2 // error FS0001: Type mismatch. Expecting a r2 [] but given a r1 [] 

두 기록이 필드 v1 있습니다. 마지막 줄에서 나는 v1 값의 튜플을 얻으려고 시도하지만 다른 레코드 유형은 r1r2입니다. 다른 레코드에 같은 이름의 필드를 선택하려고하면 오류가 발생하는 것 같습니다.

는 어떻게 든이 x1 유형 r2이어야한다는 결론에 점프, 왜 두 번째 줄은 두 개의 매개 변수 a1a2에서 유형을 추론하지 않는 이유는 무엇입니까?

편집

이 그것을 수정하지만 매개 변수의 타입 권리를 얻을 것으로 예상한다.

Array.map2 (fun (x1:r1) x2 -> (x1.v1, x2.v1)) a1 a2 // works 

답변

5

유형 검사기는 왼쪽에서 오른쪽으로 작동하므로 두 번째 예에서 충돌을 해결할만한 정보가 충분하지 않습니다. .X.Y은 각각 r1r2의 고유 한 필드이므로 첫 번째 예는 괜찮습니다. 당신은 고유의 필드를 포함 record patterns를 사용한다, 일반적으로

(a1, a2) ||> Array.map2 (fun x1 x2 -> (x1.v1, x2.v1)) 

:

이 경우 당신은 유형 검사 이전에 액세스하는 레코드 필드에 사용할 수 a1a2의 종류를 만들기 위해 배관을 사용할 수, 말했다 올바른 유형을 식별 :

Array.map2 (fun {v1 = a; X = _} {v1 = b; Y = _} -> (a, b)) a1 a2 

또는 제공 완전한 필드 이름 :

Array.map2 (fun {r1.v1 = a} {r2.v1 = b} -> (a, b)) a1 a2 
+0

감사합니다. 왼쪽에서 오른쪽으로 나에게 새로운 것이 었습니다. 기억할 것입니다. – gjvdkamp