Копирование случая объединения, но с другим значением в F # - PullRequest
3 голосов
/ 14 марта 2012

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

Какой код можно вставить вместо комментария для создания этого эффекта?

Ответы [ 3 ]

5 голосов
/ 14 марта 2012

Вы могли бы сделать

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

но единицы измерения, вероятно, лучше.

EDIT

В качестве альтернативы, может быть, вы хотите

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)
2 голосов
/ 14 марта 2012

Я думаю, что для такого рода проблем более целесообразно использовать единицы измерения - что-то вроде

[<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 голосов
/ 14 марта 2012

Вы можете создать новые значения регистра объединения, основываясь на существующем значении того же регистра объединения, используя Reflection. Чтобы добиться этого, просто добавьте элемент экземпляра 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...