Question

I want add setter property to discriminated unions, how I should to do it?

f.e.:

type Factor =    
    | Value     of Object
    | Range     of String

    let mutable myProperty = 123
    member this.MyProperty
        with get() = myProperty
        and set(value) = myProperty <- value
Was it helpful?

Solution

Here's how I might approach it:

type Value = { value: obj; mutable MyProperty: int }
type Range = { range: string; mutable MyProperty: int }

type Factor =    
    | Value     of Value
    | Range     of Range

    member this.MyProperty
        with get() = 
            match this with
            | Value { MyProperty=myProperty }
            | Range { MyProperty=myProperty } -> myProperty
        and set(myProperty) = 
            match this with
            | Value x -> x.MyProperty <- myProperty
            | Range x -> x.MyProperty <- myProperty

and use it like so:

let v = Value {value="hi":>obj ; MyProperty=0 }
v.MyProperty <- 2

match v with
| Value { value=value } as record ->
    printfn "Value of value=%A with MyProperty=%i" value record.MyProperty
| _ -> 
    printfn "etc."

I've used this technique in a similar scenario to yours with happy results in FsEye's watch model: http://code.google.com/p/fseye/source/browse/tags/2.0.0-beta1/FsEye/WatchModel.fs.

OTHER TIPS

Why not use a class and an active pattern:

type _Factor =    
    | Value_     of obj
    | Range_     of string

type Factor(arg:_Factor) =

    let mutable myProperty = 123
    member this._DU = arg
    member this.MyProperty
        with get() = myProperty
        and set(value) = myProperty <- value

let (|Value|Range|) (arg:Factor) = 
    match arg._DU with
    |Value_(t) -> Value(t)
    |Range_(t) -> Range(t)

This will obviously be significantly slower, but it allows you to do what you want

I'm not too familiar with F# yet, but I suppose you can't do this, it doesn't make any sense. Discriminated Unions as it can be seen from their name are unions. They represent some kind of a choice. And you're trying to incorporate some state into it. What're you trying to achieve? What's the use case?

Perhaps everything you need is to add additional "parameter" to your DU, i.e. if you have

type DU = 
    | A of int
    | B of string

and you want to add setter of int type, then you can extend DU in such a way:

type DU = 
    | A of int * int
    | B of string * int

    member x.Set i =
        match x with
        | A(a1, a2) -> A(a1, i)
        | B(b1, b2) -> B(b1, i)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top