Anton Minchenko
Anton Minchenko

Reputation: 461

F# how to specify when creating union case value what value to set to which field?

I have a dictionary where the key is the name of the field, and the value is this field value. Is it possible to somehow explicitly indicate to which field what value to assign using this dictionary? Or is the only way to stick to the sequence of field declarations when passing the second argument to the FSharpValue.MakeUnion?

Upvotes: 0

Views: 133

Answers (1)

Brian Berns
Brian Berns

Reputation: 17028

Two different approaches:

  1. If the names match exactly, and you're willing to "stick to the sequence of field declarations when passing the second argument to the FSharpValue.MakeUnion", you can do this:
open FSharp.Reflection

let instantiate (unionCase : UnionCaseInfo) (dict : Map<_, _>) =
    let args =
        unionCase.GetFields()
            |> Array.map (fun field ->
                 dict.[field.Name] :> obj)
    FSharpValue.MakeUnion(unionCase, args)

Example usage:

type MyType = UnionCase of a : int * b : int * c : int

let unionCase =
    FSharpType.GetUnionCases(typeof<MyType>)
        |> Array.exactlyOne

let dict =
    Map [
        "a", 1
        "b", 2
        "c", 3
    ]

instantiate unionCase dict
    :?> MyType
    |> printfn "%A"

Output is:

UnionCase (1, 2, 3)
  1. If you want to avoid reflection, you can assign to the fields in any order you want, like this:
    UnionCase (
        c = dict.["c"],
        b = dict.["b"],
        a = dict.["a"])

Upvotes: 2

Related Questions