0

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
Dmitrii Lobanov
  • 4,697
  • 1
  • 31
  • 47
nhusnullin
  • 51
  • 1
  • 1
  • 3
  • 4
    I think you should probably be using a real class for this. – John Palmer Jun 09 '12 at 07:59
  • Using discriminated unions are very convenient if you work with tree. As for me, more preferable, try find way how add setter to discriminated unions – nhusnullin Jun 09 '12 at 08:09
  • 5
    -1 XY problem. Describe the problem you are trying to solve rather than the solution yoo are failing to solve it with. – J D Jun 10 '12 at 18:46
  • I try parse and execute excel formulla. In the excel exists volitile functions, and me need marked this expresson on my tree. – nhusnullin Jun 13 '12 at 13:18
  • +1 I have been wondering how to do the same thing (it could be very useful for performance in some cases) – Demi Jul 26 '14 at 20:09

3 Answers3

5

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.

Stephen Swensen
  • 21,731
  • 9
  • 76
  • 126
2

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

John Palmer
  • 24,880
  • 3
  • 45
  • 66
1

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)
Dmitrii Lobanov
  • 4,697
  • 1
  • 31
  • 47