2017-02-04 8 views
5

私の目標は、名前と値のペアのリストをDSLに書き込んでこれを読みやすくすることです。ここでの値は、int,float,stringまたはこれらのタイプのリストです。アップキャストを使用せずに(文字列* obj)のリストを書く方法

私はstring * objのペアを使用して、(string * obj) listを受け取る関数に渡しています。

objパラメータをアップキャストしないでリストを書き込むことはできますか。

let myfun (values:(string*obj) list) = 
    // Do something... 

// This is pretty ugly 
myfun ["Name", upcast "Freddie"; "Age", upcast 50] 

// This would be the ideal 
myfun ["Name", "Freddie"; "Age", 50] 

答えて

8

プログラミング101:同じことを何度も何度も繰り返している場合は、再利用のためにパッケージ化して機能させてください。あなたのケースでは、機能は次のようになり、一般的な(すなわち、任意の型のパラメータを取る)と、パラメータにアップキャストを行います、それは非常に良く

let pair name value = name, value :> obj 
myfun [pair "Name" "Freddie"; pair "Age" 50] 

うーん...ではありませんか?しかし、待って、私たちはまだ完了していない!これであなたはこの機能を持っていますので、それをもっと素敵な名前にすることができます。 ==>、言う:

let (==>) name value = name, value :> obj 
myfun ["Name" ==> "Freddie"; "Age" ==> 50] 

可能なタイプのあなたのセットは、(あなたの質問を示しているようだとして)、あなたはさらに一歩進み、唯一許可されたタイプが使用されているコンパイラのチェックを持つことができ、事前に知られており、比較的小さい場合。これを行うには、メソッドのオーバーロード、静的に解決型制約といくつかの構文上の策略を使用する必要があります:自分の価値観だけで、特定の上場型を持つことができる

type Casters() = 
    static member cast (v: string) = v :> obj 
    static member cast (v: float) = v :> obj 
    static member cast (v: int) = v :> obj 
    static member cast (v: string list) = v :> obj 
    static member cast (v: float list) = v :> obj 
    static member cast (v: int list) = v :> obj 

let inline cast (casters: ^c) (value: ^t) = 
    ((^c or ^t) : (static member cast : ^t -> obj) value) 

let inline (==>) name value = name, (cast (Casters()) value) 

["Name" ==> "Freddie"; "Age" ==> 50] // OK 
["What?" ==> true] // Error: "bool" is not an allowed type 
+0

ありがとうございましたが、あなたの_pair_機能がタイプから私に_The静的な強制を与える」B」に、このプログラムPoint_の前の情報に基づいて不確定なタイプを必要とします。同じエラーが表示されませんか? [tryfsharp](http://www.tryfsharp.org/create/seankearon/file3.fsx) –

+2

間違いです。私はあなたの 'upcast'をコピーしました。今修正しました。 –

+0

それは素敵です、ありがとう! –

2

あなたの発言を。私はあなたが特別な理由を持っているのだろうかどうか分からない組合の代わりにobjを使用することができますか?私が代わりにobjのDUタイプを使用するには、フョードルの答えを変更した

type Value = 
    | Int  of int  | Float  of float  | String  of string 
    | IntList of int list | FloatList of float list | StringList of string list 

type Casters() = 
    static member cast v = Int v 
    static member cast v = Float v 
    static member cast v = String v 
    static member cast v = IntList v 
    static member cast v = FloatList v 
    static member cast v = StringList v 

let inline cast (casters: ^c) (value: ^t) = 
    ((^c or ^t) : (static member cast : ^t -> Value) value) 

let inline (==>) name value = name, (cast (Casters()) value) 

["Name" ==> "Freddie"; "Age" ==> 50] // OK 
["What?" ==> true] // Error: "bool" is not an allowed type 

このアプローチの利点は、あなたが値にアクセスするときに、今タイプにチェックパターンマッチングを持っているということです、そしてあなたドン「Tはobjの危険なダウンキャストをしなければならない。

let myfun (values:(string*Value) list) = 
    values 
    |> List.map (fun (k, v) -> 
     match v with 
     | Int v -> k + ":" + string v 
     | String v -> k + ":" + v.Trim()) 
     // etc. 
    |> String.concat "\n" 

myfun ["Name" ==> "Freddie"; "Age" ==> 50] |> printfn "%s" 
//Name:Freddie 
//Age:50 
+0

はい、それは非常に良い点です。私は、DSLを構成するコードに関連するこのプログラムの他の場所でこれをやっています。 –

関連する問題