2012-04-26 7 views
5

Пусть это типы =Как применить функцию к варианту?

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

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

Если я хочу, чтобы применить функцию типа А компонента А, мне нужно систематически деконструировать компонент?

для Exemple сделать я должен сделать:

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

, а затем для любой функции на компоненте А? Есть ли смысл избегать избыточности?

ответ

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

+0

Это зависит от того, что представляют данные. Мне никогда не приходилось делать что-то подобное и разрушало бы все элементы, но я также не собирался слишком долго деконструироваться и имел бы соответствующие случаи для 'B' и' C'. – nlucaroni

Смежные вопросы