3

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

我可以插入什么代码来代替注释来创建这种效果?

4

3 回答 3

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)
于 2012-03-14T02:24:46.137 回答
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

转换功能有点棘手,但它会做你想要的

于 2012-03-14T02:15:37.177 回答
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

于 2012-03-14T14:42:17.873 回答