2012-03-14 17 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

相关问题