2012-03-14 15 views
3

在F#中,我想根據現有實例構造一個區分聯合的實例(正確的術語?)。例如:在F#中複製一個工會案例但具有不同的值

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 *) 

我可以插入什麼代碼來代替創建該效果的註釋?

+0

換句話說,你想同工會的新值的通用能力沒有打擾的情況下找到什麼是這種確切的情況?似乎很自然地使用Reflection來實現這一點(請參閱下面的答案)。 – 2012-03-14 15:07:15

回答

5

你可以做

let highPrice = 
    let n = 200 
    match lowPrice with 
    | Dollar _ -> Dollar n 
    | Euro _ -> Euro n 

但測量單位可能會更好。

編輯

或者,也許你想

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) 
+0

嗯,所以沒有更乾淨的方法呢?當你有很多工會案例時,這會變得有點麻煩,但似乎這是最簡單的方法。正如我上面所說,我應該已經清楚,這實際上不是貨幣問題,所以度量單位不起作用。 – Martin 2012-03-14 02:28:42

+0

請參閱我所做的修改。 – Brian 2012-03-14 03:30:35

+0

我認爲那可能是我們的贏家!謝謝,Brian。 – Martin 2012-03-14 06:53:00

2

我認爲對於這類問題更適合使用的度量單位 - 財產以後像

[<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 

的轉換功能是有點棘手,但它會做你想要什麼

+0

對不起,我應該已經更清楚了。這不是一個測量問題;我只是以貨幣爲例。 – Martin 2012-03-14 02:26:34

+0

@Martin - 我明白了 - 你可以使用其他類型的Measure類型,這可能是一個很好的解決方案。如果你使用工會,這將是討厭的,因爲他們不是爲此而設計的。 – 2012-03-14 02:34:35

0

您可以根據使用反射同工會的情況下現有的價值做出新的工會情況下的值。爲了實現這一目標只是實例成員Same添加到您的可識別的聯合,它首先從實例self得出具體的聯合情況,然後由同工會的情況下構建了一個新的實例,但現在填充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 

現在把它應用到lowPrice值低於

let lowPrice = Euro(100) 
let highPrice = lowPrice.Same 200 

你會得到highPrice : Currency = Euro 200

相關問題