Create Discriminated Union Case from String

前端 未结 3 1060
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-06 05:32

I\'m trying to create DU cases from strings. The only way I can see doing this is by enumerating over the DU cases via Microsoft.FSharp.Reflection.FSharpType.GetUnionC

相关标签:
3条回答
  • 2020-12-06 06:03

    I found this handy code snippet...

    open Microsoft.FSharp.Reflection
    
    let toString (x:'a) = 
        let (case, _ ) = FSharpValue.GetUnionFields(x, typeof<'a>)
        case.Name
    
    let fromString<'a> (s:string) =
        match FSharpType.GetUnionCases typeof<'a> |> Array.filter (fun case -> case.Name = s) with
        |[|case|] -> Some(FSharpValue.MakeUnion(case,[||]) :?> 'a)
        |_ -> None
    

    ... which makes it easy to tack on two lines of code to any DU...

    type A = X|Y|Z with
        override this.ToString() = FSharpUtils.toString this
        static member fromString s = FSharpUtils.fromString<A> s
    
    0 讨论(0)
  • 2020-12-06 06:10

    I would use pattern matching like this:

    type Keyword = 
        | FOO
        | BAR
        | BAZ
        | BLAH
    
    
    let matchKeyword (word:string) : Keyword option =
        match word with
        | "FOO"  -> Some FOO
        | "BAR"  -> Some BAR
        | "BAZ"  -> Some BAZ
        | "BLAH" -> Some BLAH
        | _      -> None
    

    And maybe auto generate the match statement first time using regex in my editor, but only because you have hundreds of cases. But i am not sure if its a better solution then yours.

    0 讨论(0)
  • 2020-12-06 06:26

    As the cases have no value, another option is to use enums:

    type Keyword = 
      | FOO   = 0
      | BAR   = 1
      | BAZ   = 2
      | BLAH  = 3
    
    let strings = ["FOO";"BAR"]
    let keywords = 
      [for s in strings -> s, Keyword.Parse(typeof<Keyword>, s)]
      |> Map.ofList
    

    Then you can simply use Enum.Parse.

    0 讨论(0)
提交回复
热议问题