2013-08-07 4 views
3

하나의 함수가 다른 레코드 유형에서 동일한 레이블을 호출하도록 할 수 있습니까? 예하나 이상의 레코드 유형에서 동일한 라벨에 액세스하는 방법은 무엇입니까?

type Pen = { 
    Diameter: float 
    InkColor: string 
} 

type Pencil = { 
    Diameter: float 
    Hardness: int 
    Blackness: int 
} 

아래에 정의 된 두 개의 기록이있다 말할 수를 위해 나는 함수 중 하나를 기록 유형에서 직경 라벨에 액세스 할 수 있나요? 지금 펜과 연필을 정의하면 컴파일러는 사용할 레코드 유형을 혼동합니다. 문제는 컴파일러에서 형식을 선택하는 것이 아니라 원하는 형식을 선택하면 두 형식을 모두 사용할 수있게하려는 것입니다. 이 예제는 연필을 기대하기 때문에 컴파일되지 않을 것입니다. 지금 볼

let black_pen = { 
    Diameter = 0.7 
    InkColor = "Black" 
} 

let mechanical_pencil = { 
    Diameter = 0.5 
    Hardness = 1 
    Blackness = 2 
} 

let getDiameter writing_utility = 
    let {Diameter = dia} = writing_utility 
    dia 

printf "%A" (getDiameter black_pen) 

내 유일한 옵션은 다음과 같습니다

  1. 어떤 객체 인 말 열거 형식으로 레코드를 결합합니다.

    :이 같은 뭔가 제네릭을 사용할 수있는 경우 패턴 일치
  2. 사용 클래스 대신 그것은 좋은 것

을 라벨을 확인하고 입력

  • 사용을 동적 타입과 반사를 상속 사용
    let getDiameter writing_utility = 
        let {Diameter<float> = dia} = writing_utility 
        dia 
    

    레코드에 "Diameter"레이블이 있고 float 인 한이 값이 반환됩니다.

  • 답변

    5

    당신은 정말이에 대한 상속을 사용하지만 다음 작품 아래에 다른 옵션의

    let inline getDiameter (t:^q when ^q :(member Diameter:float)) = 
        (^q : (member Diameter:float) t);; 
    
    +0

    금괴에 감사드립니다. – Gorilla3D

    2

    커플해야한다.

    함수로 "직경 것"에서에 "직경"매핑을 제공합니다 :

    let getDiameter (util:'a) (diamFunc:'a->float) = 
        let dia = diamFunc util 
        dia 
    
    getDiameter black_pen (fun x -> x.Diameter) 
    getDiameter mechanical_pencil (fun x -> x.Diameter) 
    

    아니면 청소기를, 하위 사용자 (F # 3.1라는 이름의 DU 필드 구문을 잘 사용)를 사용 :

    type WritingImplement = 
        | Pen of diameter:float * inkColor:string 
        | Pencil of float * int * int // 3.0 syntax 
    
    let black_pen = Pen(diameter = 0.7, inkColor = "Black") 
    let mechanical_pencil = Pencil(0.5, 1, 2) // 3.0 syntax 
    
    let getDiameter = function 
        | Pen(diameter = d) -> d 
        | Pencil(d, _, _) -> d // 3.0 syntax 
    
    2

    getDiameter에 대해 생각해보십시오. somethingfloat, 즉 'a -> float으로 매핑합니다. 그러나 'a은 무엇이든 될 수 있으며 아무 것도 알지 못해도 float 값으로 매핑 할 수 있다는 의미이므로 의미가 없습니다. 우리는 float 값을 얻기 위해 전달 된 물건에 대한 몇 가지 속성을 알고 있는지 확인해야합니다. 즉, <something with Diameter> -> float과 같은 것을 원합니다. 그리고 뭔가에 대한 제약을 표현하는 가장 좋은 방법은 지금 서명이 IWithDiameter -> float이되도록 인터페이스를 사용하는 것입니다.

    관련 문제