2012-04-26 62 views
5

讓這個類型=如何將函數應用於變體?

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

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

如果我想在一個類型的組件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*) 

,然後在A組份的任何功能?有沒有任何意思來避免你的冗餘?

回答

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); 
} 

如果您不想有每次寫(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) } 

你可以做同樣的事情用函子,但這在我看來,這成爲矯枉過正。

3

您可以通過一個高階函數到該組件的破壞你的函數,

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

的類型,這將是,

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

正如你所看到的,多態適用於任何值爲A的任何函數。此外,大多數人遠離捕捉所有,_,而不是徹底的。

+0

我明白了;這是處理這個問題的標準方法嗎?是否有可能使模塊更具通用性? – codablank1 2012-04-26 17:50:41

+0

這取決於數據表示的內容。我從來沒有需要做這樣的事情,並會破壞所有的元素,但我也不會經常解構,並會有適當的'B'和'C'的情況。 – nlucaroni 2012-04-26 17:54:03