2012-04-26 16 views
5

lasciate che questo tipo =Come applicare una funzione a una variante?

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

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

Se voglio applicare una funzione del tipo di una di un componente A, devo sistematicamente di decostruire la componente?

per exemple devo fare:

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

e quindi per qualsiasi funzione su un componente A? C'è qualche mezzo per evitare la tua ridondanza?

risposta

4

Dipende molto dal tipo di operazione che si eseguirà sui tipi.

La soluzione data dalla @nlucaroni è perfettamente bene, ma se si vuole fare qualcosa di un po 'più generico (e complesso) è possibile utilizzare un record di tenere le funzioni della mappa parziali:

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

Se non vogliono avere a scrivere la funzione (fun _ -> None) ogni volta, è anche possibile utilizzare un valore di default che si estende:

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

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

si può fare le stesse cose con funtori, ma questo a mio parere questo diventa eccessivo.

3

è possibile passare un ordine-funzioni superiore a una funzione che fa la distruzione di componenti per voi,

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

Il tipo di questo sarebbe,

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

Come si può vedere, polimorfico per qualsiasi funzione applicata a qualsiasi valore di A. Inoltre, la maggior parte delle persone evita il catch-all, _, e per essere esauriente.

+0

Vedo; è un modo standard per gestire questo problema? Sarebbe possibile renderlo ancora più generico con i moduli? – codablank1

+0

Dipende da ciò che i dati rappresentano. Non ho mai avuto bisogno di fare qualcosa del genere e avrei distrutto tutti gli elementi, ma anch'io non avrei decostruito troppo spesso, e avrei avuto casi appropriati per 'B' e' C'. – nlucaroni

Problemi correlati