ca9163d9
ca9163d9

Reputation: 29199

Replace the value of one item of single case discriminated union?

See I have a single case discriminated union

type R = R of string * int * sting option * .....

And I got a value of R.

let r: R = getAValue ()

Now I need to replace the first item of r to an empty string and keep all other value. How to do it? Record type has the with construct

let r' = { r with Item1 = "" }

I know it can use 'pattern match' to extract all the items and create a new one. But it seems very cumbersome.

Upvotes: 1

Views: 97

Answers (1)

Gene Belitski
Gene Belitski

Reputation: 10350

I assume you do not want to involve reflection, do you?

Then, I believe your only option would be using pattern matching. The (quite limited) burden would be defining the r-ity of your type Ras a pattern for matching.

Let's assume, for example, that your R wraps a tuple of 3 elements, i.e. has r-ity 3:

type R = R of string * int * string option

In this case all you need is to do define the following function:

let modR = function
| R(x,y,z) -> R("",y,z)

The signature of modR is R -> R, a quick check of your scenario:

let r = R("abc",1,None)
modR r

in fsi brings back

> 
val it : R = R ("",1,None)

All you would need for applying the above to your specific R is set the actual r-ity of your type into the pattern.

UPDATE: As Fyodor Soikin pointed, a matching function isn't needed at all for unwrapping a single-case DU (see the docs). The sought convertion function definition may be defined as simple as

let modR (R(_,y,z)) = R("",y,z)

UPDATE2: While considering the comment from ca9163d9 I recalled just another flavor of pattern matching, namely as Pattern. Using it while implementing the sought conversion in the form of DU member gives:

type R = R of string * int * string option with
    member self.modR() = let R(_,b,c) as x = self in R("",b,c)

Also @FyodorSoikin and @kaefer have pointed out in the comments that as x form isn't required for the simple DU unwrapping, similarly to terser modR function definition above:

    member self.modR() = let (R(_,b,c)) = self in R("",b,c)

Upvotes: 3

Related Questions