Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a pattern match the only way to get data associated with a union case?

Let's say you have this union:

type Thing = 
| Eagle
| Elephant of int

And your code has a list of Elephants, as in

let l = [Elephant (1000); Elephant (1200)]

And you wanted to iterate over l, and print out the data associated with each Elephant. Is there a way to do so without using a pattern match?

like image 923
Michael Ray Lovett Avatar asked May 27 '15 15:05

Michael Ray Lovett


2 Answers

In your example, you say that you have a list of elephants - which is true in this case - but the type of l is really a list of Thing values and so it can contain both elephants and eagles. This is why you need to use pattern matching - to handle all possible cases.

If you regularly need to use list that contain only elephants, then it might make sense to define a separate type of elephants. Something like:

type ElephantInfo = { Size : int }

type Thing = 
  | Elephant of ElephantInfo
  | Eagle

Now you can create a list of type list<ElephantInfo> which can contain just elephants and so you don't need pattern matching:

let l1 = [ {Size=1}; {Size=2} ]
for el in l1 do printfn "%d" el.Size

On the other hand, if you want to mix elephants and eagles, you'll create list<Thing> and then use pattern matching:

let l2 = [ Elephant {Size=1}; Eagle ]
like image 140
Tomas Petricek Avatar answered Sep 20 '22 04:09

Tomas Petricek


You could do this:

l
|> List.collect (function Elephant x -> [x] | _ -> [])
|> List.iter (printfn "%i")

Prints

1000
1200

It still uses pattern matching, but it's fairly minimal.

like image 29
Mark Seemann Avatar answered Sep 22 '22 04:09

Mark Seemann