2012-04-26 17 views
5

dejar que este tipo =¿Cómo aplicar una función a una variante?

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

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

Si quiero aplicar una función del tipo A de un componente A, ¿necesito sistemática de deconstruir el componente?

para exemple hacer lo que tengo que hacer:

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

y luego para cualquier función en un componente A? ¿Hay alguna forma de evitar tu redundancia?

Respuesta

4

Realmente depende de qué tipo de operación realizará en sus tipos.

La solución dada por @nlucaroni está perfectamente bien, pero si quieres hacer algo un poco más genérica (y complejo) que puede utilizar un registro para mantener sus funciones mapa parcial:

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

Si no quiero tener que escribir la función (fun _ -> None) cada vez, también se puede utilizar un valor predeterminado que se amplía:

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

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

usted puede hacer lo mismo con palabras funcionales, pero esto en mi opinión, esto se convierte en un exceso.

3

puede pasar un pedido-función superior a una función que hace la destrucción de componentes para usted,

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

El tipo para esto sería,

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

Como se puede ver, polimórfico para cualquier función aplicada a cualquier valor de A. Además, la mayoría de las personas se mantienen alejadas del catch-all, _, y en su lugar son exhaustivas.

+0

Veo; ¿Es una forma estándar de manejar este problema? ¿Sería posible hacerlo aún más genérico con módulos? – codablank1

+0

Depende de lo que representan los datos. Nunca tuve que hacer algo como esto y destruiría todos los elementos, pero tampoco estaría deconstruyendo demasiado a menudo, y tendría casos apropiados para 'B' y' C'. – nlucaroni

Cuestiones relacionadas