Accessing specific case from F# DU

discriminated-union, f#

Solution

The important thing to note is that `A` and `B` are constructors of the same type `Something`. So you will get inexhaustive pattern matching warning if you try to use `A` and `B` cases separately.

IMO, deconstructing all cases of DUs is a good idea since it is type-safe and forces you to think of handling those cases even you don't want to. The problem may arise if you have to deconstruct DUs repetitively in the same way. In that case, defining `map` and `fold` functions on DUs might be a good idea:

let mapSomething fa fb = function
| A(i) -> fa i
| B(s, i) -> fb s i

Please refer to excellent Catamorphism series by @Brian to learn about fold on DUs.

That also said that your example is fine. What you really process are `string` and `int` values after deconstruction.

You can use Active Patterns to consume two cases separately:

let (|ACase|) = function A i -> i | B _ -> failwith "Unexpected pattern B _"
let (|BCase|) = function B(s, i) -> (s, i) | A _ -> failwith "Unexpected pattern A _"

let doSomethingWithA (ACase i) = ....

but inferred type of `doSomethingWithA` is still the same and you get an exception when passing `B _` to the function. So it's a wrong thing to do IMO.

Problem

Suppose I have the following DU: ``` type Something = | A of int | B of string * int ``` Now I use it in a function like this: ``` let UseSomething = function | A(i) -> DoSomethingWithA i | B(s, i) -> DoSomethingWithB s i ``` That works, but I've had to deconstruct the DU in order to pass it to the DoSomethingWith* functions. It feels natural to me to try to define DoSomethingWithA as: ``` let DoSomethingWithA (a: Something.A) = .... ``` but the compiler complains that the type A is not defined. It seems entirely in keeping with the philosophy of F# to want to restrict the argument to being a Something.A, not just any old int, so am I just going about it the wrong way?

Original source