2014-09-16 2 views
0

, get_Zero의 형태 제약주의 : 이미 명시 적 타입 제약 조건이 있지만F # 누락 형 제약

type Wrapper<'t> = { Data : 't[] } 

let compute<'t 
    when 't : (static member get_Zero : unit -> 't) 
    and 't : (static member (~-) : 't -> 't) 
    and 't : (static member (+) : 't * 't -> 't)> 
     (wrapper : Wrapper<'t>) = 
    wrapper.Data 
     |> Seq.mapi (fun i value -> (i, value)) 
     |> Seq.sumBy (fun (i, value) -> 
      if i % 2 = 0 then value 
      else -value) 

을, 나는 아직도 서열에 대한 호출에 다음과 같은 컴파일러 오류를 받고 있어요 .sumBy :

A 형 파라미터는 제약 '(고정 부재 get_Zero ->^t)^때 t'누락

상관 여기서 무슨 일이 벌어지고 있는지 알아? 감사.

답변

7

다운 스트림 정적 멤버 제약 조건을 명시 적으로 지정하면 좌절감을 느낄 수 있으며, 다행스럽게도 거의 필요하지 않습니다. 그냥 함수 inline을 표시하고 유추 할 수 있습니다.

let inline compute (wrapper : Wrapper<_>) = 
    wrapper.Data 
    |> Seq.mapi (fun i value -> (i, value)) 
    |> Seq.sumBy (fun (i, value) -> 
     if i % 2 = 0 then value 
     else -value) 

올바른 서명은 다음과 같습니다

let inline compute<'t 
      when 't : (static member Zero : 't) 
      and 't : (static member (~-) : 't -> 't) 
      and 't : (static member (+) : 't * 't -> 't)> 

이 (당신은 오류 메시지의 서명을 알 수있다조차 유효한 구문은 다음과 같습니다. when ^t : (static member get_Zero : -> ^t) 이것은 내가 좌절 무엇을 의미의 일부입니다.)

+1

인라인 버전이 작동하는 이유는 무엇입니까? 컴파일러는 제약 조건을 추론합니다. 'sumBy'는 인라인이며, 그것의 제약 조건은 그것을 인라인으로 표시함으로써 소비 함수로 전달됩니다. – Daniel

+0

이 방법이 효과적이지만 질문에는 실제로 대답하지 않습니다. 또한 "compute"함수를 호출하는 유형 확장자에서는 작동하지 않는 것으로 보입니다 : 'type 래퍼 <'t> 멤버 인라인 wrapper.Compute = wrapper |> compute' – brianberns

+1

@brianberns : 작업 서명으로 답변을 업데이트했습니다. 형식 확장은 형식에 정의 된 제네릭 인수를 사용하고 형식 수준 제네릭 인수에 대한 제약 조건은 명시 적이어야하므로 작동하지 않습니다. – Daniel