8

I have a discriminated union type:

type F =
| A of int
| B of float

Suppose I have a list of F that has been filtered to yield only objects of type A:

let listOfAs=list.filter (fun f -> match f with | A(f') -> true | _ -> false)

How can I work with the resulting list of F without requiring pattern matches everywhere in my code? The compiler doesn't like a direct cast, eg

list.map (fun f -> int f) listOfAs
Robert Sim
  • 1,428
  • 11
  • 22

1 Answers1

13

You cannot really cast discriminated union value - the type of F is a different thing than the type int (it is not like C union where they have the same binary representation).

So, the easiest solution is to write a function that takes list<F> and returns list<int> containing only the int values that were wrapped in the A case.

To do this, you can use List.choose (instead of List.filter). This lets you specify a projection where you can return None (meaning skip the value) or Some v (meaning return value v as part of the resulting list):

let listOfAs = List.choose (fun f -> 
  match f with 
  | A(f') -> Some f'
  | _ -> None)
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • 1
    On a side note, the code can be shortened by one line by replacing `fun f ->` with the `function` keyword and removing the `match` line. – Vandroiy Nov 24 '14 at 20:00
  • 3
    Yes, it can be :-) I do not usually do this when showing code because it requires explaining two things at once! – Tomas Petricek Nov 25 '14 at 14:09