Copying a union case but with a different meaning in F #
In F #, I want to construct an instance (correct terminology?) Of a discriminatory join based on an existing instance. Example:
type union Currency =
| Dollar of int
| Euro of int
let lowPrice = Dollar 100 (* or, it could be *) let lowPrice = Euro 100
let highPrice = (* of the same union case as lowPrice but with value 200 *)
What code can be inserted instead of a comment to create this effect?
source to share
You could do
let highPrice =
let n = 200
match lowPrice with
| Dollar _ -> Dollar n
| Euro _ -> Euro n
but units are probably better.
EDIT
Alternatively, perhaps you want
type MoneyType = Dollar | Euro
type Currency = Currency of MoneyType * int
let lowPrice = Currency(Dollar, 100)
let highPrice =
match lowPrice with
| Currency(kind, _) -> Currency(kind, 200)
source to share
I think it makes more sense to use units for this kind of problem - somthing like
[<Measure>] type Dollar
[<Measure>] type Euro
let lowprice = 100<Dollar>
let inline _highprice (newv:int) (oldv:int<'t>) : int<'t> =
LanguagePrimitives.Int32WithMeasure newv
let highprice = _highprice 200 lowprice
the transform function is a little tricky but will do what you want
source to share
You can introduce new case union values ββbased on the existing value of the same case union using Reflection. To achieve this, simply add a member instance Same
to your discriminated union, which first deduces the specific case of the union from the instance self
, and then creates a new instance with the same case of the union, but is now populated with newVal
:
open Microsoft.FSharp.Reflection
type Currency =
| Dollar of int
| Euro of int
member self.Same newVal : Currency =
FSharpValue.MakeUnion(fst (FSharpValue.GetUnionFields(self,
typeof<Currency>)), [|newVal|])
|> unbox
Now applying it to lowPrice
below value
let lowPrice = Euro(100)
let highPrice = lowPrice.Same 200
You'll get highPrice : Currency = Euro 200
source to share