2017-03-09 5 views
2

나는 F #을 배우는 중입니다. 올바른 유형의 유추 된 유형을 대체 할 때 왜 List.Filter과 다른 유형을 추론하는지에 대해 머리를 감싸려고합니다. . 코드는 수천 단어에 해당합니다.F # 레코드로 유추 된 이상한 행동

type Account = 
{ account : int 
    label : string } 

type Journal = 
{ account : int 
    period : string 
    debit : int 
    credit : int } 

let outputJournal (journals: Journal List) (account:Account) = 
    let filtered = List.filter (fun x -> x.account = account.account) journals 
    filtered 

지정된 계정에 대한 저널 목록을 필터링해야합니다. 그러나 outputJournal 함수는 List.filter에 전달 된 journals 인수 아래의 오류를 출력합니다. "계정 목록이 필요하지만 '목록 업무 일지'가 지정되었습니다. '계정'유형이 '업무 일지'유형과 일치하지 않습니다."라는 오류가 있습니다.

필자는 왜 저널 목록을 필터링하려고하는지 분명히 생각하고있는 것처럼 혼란 스럽습니다. 형식 유추를 재정의하여 컴파일러에게 명확한 의도를 부여하거나 다른 의도를 내릴 수있는 방법이 있습니까 (어느 레코드에서 계정 필드의 이름을 바꾸는 것이 옵션이지만이를 피하고 싶습니다)?

매우 감사드립니다. 고맙습니다.

+3

유형 추론은 오른쪽에서 왼쪽입니다. 주석 달기 타입 x –

+0

@JohnPalmer 많이 감사드립니다! 미래에 알게되면 매우 도움이 될 것입니다. –

+5

'journals |> List.filter (fun ...' –

답변

5

F #의 형식 유추는 왼쪽에서 오른쪽으로 stricktly 위쪽에서 아래쪽으로 진행됩니다.

결과적으로 x.account을 수행하면 컴파일러에서 xAccount 인 것으로 추측하므로 오류 메시지가 나타납니다.

이 문제를 해결하려면, 당신은 두 가지

1

) x의 유형

let filtered = List.filter (fun (x:Journal) -> x.account = account.account) journals 

2) 파이프 연산자 순서를 변경 주석을 수행 할 수 있습니다 (감사 표도르)

let filtered = journals |> List.filter (fun x -> x.account = account.account) 

방식 유추 작업 때문에 (2)가 더 일반적입니다.

+1

...와 같이'List.filter' 앞에'journals'을 넣을 수도 있습니다. –