3

1 つの関数で異なるレコード タイプから同じラベルを呼び出すことは可能ですか? たとえば、以下に定義されている 2 つのレコードがあるとします。

type Pen = {
    Diameter: float
    InkColor: string
}

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

いずれかのレコード タイプから Diameter ラベルにアクセスする関数を作成できますか? 現在、ペンと鉛筆を定義すると、コンパイラはどのレコード タイプを使用するかで混乱します。問題は、コンパイラに型を選択させたくないということです。コンパイラが何かを選択した場合、両方の型の使用を許可します。この例は鉛筆を想定しているため、コンパイルされません。

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. 代わりにクラスを使用して継承を使用する
  3. 動的な型とリフレクションを使用して、ラベルと型を確認します

次のようなものにジェネリックを使用できればいいのですが。

let getDiameter writing_utility = 
    let {Diameter<float> = dia} = writing_utility
    dia

これは、レコードに「Diameter」というラベルがあり、フロートである限り、値を返します。

4

3 に答える 3

5

これには本当に継承を使用する必要がありますが、次のように機能します

let inline getDiameter (t:^q when ^q :( member Diameter:float)) = 
    (^q : (member Diameter:float) t);; 
于 2013-08-07T02:52:32.493 に答える
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)

または、よりクリーンな場合は、DU を使用します (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
于 2013-08-07T06:31:44.550 に答える
2

どうするか考えてgetDiameterください。それはieにマップsomethingされますが、意味がありません。なぜなら、それが何かである可能性があり、何かを知らずにその何かを値にマッピングすることはうまくいかないからです。値を取得するには、渡されたものに関するいくつかのプロパティを知っていることを確認する必要があります。float'a -> float'afloatfloat<something with Diameter> -> floatIWithDiameter -> float

于 2013-08-07T08:26:01.400 に答える