5

Let this types =

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

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

If I want to apply a function on the type a of a component A, do I need systematically to deconstruct the component ?

for exemple do i have to do :

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

and then for any function on a component A ? Is there any mean to avoid thy redundancy ?

codablank1
  • 6,055
  • 5
  • 19
  • 29

2 Answers2

4

It really depends which kind of operation you will perform on your types.

The solution given by @nlucaroni is perfectly fine, but if you want to do something a bit more generic (and complex) you can use a record to hold your partial map functions:

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

If you don't want to have to write the (fun _ -> None) function every time, you can also use a default value that you extend:

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

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

You can do the same things with functors but this in my opinion this becomes overkill.

Thomas
  • 5,047
  • 19
  • 30
3

You can pass a higher-order-function to a function that does the component destruction for you,

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

The type for this would be,

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

As you can see, polymorphic for any function applied to any value of A. Also, most people stay away from the catch-all, _, and to be exhaustive instead.

nlucaroni
  • 47,556
  • 6
  • 64
  • 86
  • I see; is it a standard way to handle this problem ? Would it possible to make it even more generic with modules ? – codablank1 Apr 26 '12 at 17:50
  • It depends on what the data represents. I have never needed to do something like this and would destruct all the elements, but I also wouldn't be deconstructing too often, and would have appropriate cases for `B` and `C`. – nlucaroni Apr 26 '12 at 17:54