2016-08-25 8 views
3

汎用レコードをインスタンス化するときに、型パラメーターを明示的に指定したいとします。別の言葉で言えば、RecordType<'T1, 'T2, 'T3>を指定すると、のインスタンスを作成して、それらの汎用パラメータを指定することによって、固定の'T1,'T2および'T3を作成します。 F#でそれを行う方法はありますか?明示的な型パラメータを持つ汎用レコードをインスタンス化する方法は?

私はそれが便利だ3例参照

  1. は、同じ名前を持つ複数のジェネリック型があるとき

    は、我々は、レコードの定義を以下していると仮定したレコードのインスタンス化

    type SimpleGenericRecord<'T1, 'T2> = { 
        f1 : 'T1 -> 'T2 
    } 
    
    type SimpleGenericRecord<'T> = { 
        f1 : 'T -> 'T 
    } 
    

    私は容易にSimpleGenericRecord<'T>のインスタンスを構成します。 は、最後に定義された:コンパイルエラーを を与えるSimpleGenericRecord<int, int>を作成しようとする試みに続き

    let record = { 
        f1 = fun (x: int) -> 0 
    } 
    
    let record1 = { 
        SimpleGenericRecord.f1 = fun (x: int) -> 0 
    } 
    

    let record2 = { 
        SimpleGenericRecord<int, int>.f1 = fun (x: int) -> 0 
    } 
    
    let record3 = { 
        SimpleGenericRecord<_, _>.f1 = fun (x: int) -> 0 
    } 
    

    私は2つのタイプのための同じレコード名を持つことが最高のアイデアではないかもしれないことを知っているが、それにもかかわらず、私は思いますその言語は私に両方のタイプを使用する方法を与えるはずです。レコードタイプ

    F# referenceを文書化

  2. は言う:

    レコードフィールドでのDefaultValue属性を使用しないでください。より良い のアプローチは、 が初期値に初期化されたフィールドを持つレコードのデフォルトインスタンスを定義してから、 レコード式のコピーと更新を使用して、デフォルトの 値とは異なるフィールドを設定します。

    このアドバイスに続いて、私はレコードのデフォルトインスタンスを定義したいと思います。それらはパブリックAPIの一部であるため、そのタイプを記録します。レコードタイプの

    ジェネリックパラメータ型推論に支援

  3. は、レコードの値の型を推測するために使用することができます。

    は私が持っていると仮定します

    type RecordWithSomeComplexType<'T> = { 
        t1 : int -> System.Collections.Generic.Dictionary<int, 'T> // some long type signature 
    } 
    

    、私はそれをインスタンス化します。タイプ注釈を指定しない場合、レコードの値は可能な限り一般的になります。

    let record4 = { 
        RecordWithSomeComplexType.t1 = failwith "Intentionally failing" 
    } 
    

    int -> System.Collections.Generic.Dictionary<int, obj> 
    

    Iが特定のタイプであることがレコードを強制することができる(例えば、型を持ちますRecordWithSomeComplexType<string>)、その場合、私は特定の値の完全な型を書く必要があります。

    let failing = { 
        RecordWithSomeComplexType.t1 = 
         failwith "Intentionally failing" :> int -> System.Collections.Generic.Dictionary<int, string> 
         // I don't want to provide a full type of a value here 
    } 
    

    コンパイラは、私がRecordWithSomeComplexType<string>にしたいことを知っていたならば、それは価値の署名を推測することができます。

+0

コンパイルエラーがありますか? –

+0

@FyodorSoikin "フィールドバインディングの形式は 'id = expr;'"でなければなりません。ありがとうございます。 –

答えて

5

あなたはかなりどこでも

let record2 : SimpleGenericRecord<_, _> = { 
    f1 = fun (x: int) -> 0 
} 

// alternative 
let record2 = 
    ({ 
    f1 = fun (x: int) -> 0 
    } : SimpleGenericRecord<_, _>) 

そして、あなたが物事にRECORD4評価が上昇してしまうことに

type Alias<'T> = int -> System.Collections.Generic.Dictionary<int, 'T> 

let record4 = { 
    t1 = (failwith "Intentionally failing" : Alias<string>) 
} 

注意を容易にするために、エイリアスの種類を書くことができ、より長い場合のために型注釈を追加することができます遅れていないので即座に例外が発生する

+0

それは愚かな質問だった。 failwithに関しては、よく知られている関数であり、狭めることができるタイプであるため、私は単にそれを使いました。 –

関連する問題