2012-04-26 4 views
5

このタイプをしてみましょう=バリアントに関数を適用する方法は?

type intC = int;; 
type boolC = bool; 
type stringC = string;; 

type component = A of intC | B of boolC | C of stringC;; 

私はA成分の種類に機能を適用したい場合は、私が部品を分解するために体系的に必要がありますか? A成分上の任意の機能のための

let add comp = 
    match comp with 
    | A i -> Some (i + 2) (*only A interests me, I return i + 2*) 
    | _ -> None   (*otherwise I return nothing*) 

、その後の:exempleため

は私がしなければならないのですか?あなたの冗長性を避ける手段はありますか?

答えて

4

実際には、どの種類の操作を実行するかによって異なります。

@nlucaroniによって与えられた解決策は完全に罰金ですが、もう少し一般的な(かつ複雑な)何かをしたい場合は、あなたの部分地図機能を保持するために、レコードを使用することができます。

type 'a component_m = { 
    a : intC -> 'a; 
    b : boolC -> 'a; 
    c : stringC -> 'a; 
} 

let map_component m = function 
    | A a -> m.a a 
    | B b -> m.b b 
    | C c -> m.c c 

let add = map_component { 
    a = (fun x -> Some (x + 2)); 
    b = (fun _ -> None); 
    c = (fun _ -> None); 
} 

あなたの場合あなたはファンクタと同じことを行うことができますが、これは私の意見では、これはやり過ぎとなり

let none = { 
    a = (fun _ -> None); 
    b = (fun _ -> None); 
    c = (fun _ -> None); 
} 

let add = map_component { none with a = fun x -> Some (x+2) } 

(fun _ -> None)機能を毎回書く必要がしたくない、あなたはまた、あなたが拡張し、デフォルト値を使用することができます。

3

あなたが見ることができるようにあなたは、このためのタイプは次のようになり、あなたのためのコンポーネントの破壊を行う関数に

val apply_if_a : (int -> 'a) -> component -> 'a option 

let apply_if_a f = function 
    | A i   -> Some (f i) 
    | (B _ | C _) -> None 

を高次関数を渡すことができますAの任意の値に適用される関数の多型。また、ほとんどの人はキャッチオール_から離れ、代わりに網羅的である。

+0

です。この問題を処理するのは標準的な方法ですか?それをモジュールでさらに汎用化することは可能でしょうか? – codablank1

+0

データの内容によって異なります。私はこのようなことをする必要は一度もなく、すべての要素を破壊するだろうが、私はあまりにも頻繁に解体することはなく、 'B'と' C'の適切な場合があるだろう。 – nlucaroni