Copiare un caso sindacato ma con un valore diverso in f #
-
13-12-2019 - |
Domanda
In F #, voglio costruire un'istanza (terminologia corretta?) di un'unione discriminata basata su un'istanza esistente.Esempio:
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 *)
.
Quale codice potrei inserire al posto del commento per creare quell'effetto?
Soluzione
Potresti fare
let highPrice =
let n = 200
match lowPrice with
| Dollar _ -> Dollar n
| Euro _ -> Euro n
.
Ma le unità di misura sono probabilmente migliori.
Modifica
In alternativa, forse vuoi
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)
. Altri suggerimenti
Penso che per questo tipo di problema sia più appropriato usare unità di misura - qualcosa come
[<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
.
La funzione di conversione è un po 'complicata ma farà ciò che vuoi
È possibile effettuare nuovi valori del caso dell'Unione in base al valore esistente della stessa custodia dell'Unione utilizzando la riflessione.Per ottenere questo solo aggiungere il membro dell'istanza Same
alla tua sindacata discriminata, che prima deriva la custodia specifica dell'Unione dall'istanza self
e quindi costruisce una nuova istanza con lo stesso caso dell'Unione, ma ora popolata con 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
.
Ora applicandolo al valore lowPrice
sotto
let lowPrice = Euro(100)
let highPrice = lowPrice.Same 200
.
Otterrai highPrice : Currency = Euro 200