我正在尝试从字符串创建DU案例.我可以看到这样做的唯一方法是通过枚举DU情况Microsoft.FSharp.Reflection.FSharpType.GetUnionCases
,然后选择UnionCase
匹配字符串(通过使用.Name
),然后通过使用实现DU的情况FSharpValue.MakeUnion
.
这样做是不是更简单/更优雅?在我的场景中,我有一个DU,有几百个关键字案例.我必须从文件中读取字符串(关键字)并从中提取类型.通过将案例放入Map中我做了一些"优化",但我希望有更好的方法来做到这一点.
我有以下内容,例如:
type Keyword = | FOO | BAR | BAZ | BLAH let mkKeywords (file: string) = use sr = new StreamReader(file) let caseMap = FSharpType.GetUnionCases(typeof) |> Array.map (fun c -> (c.Name, FSharpValue.MakeUnion(c, [||]) :?> Keyword)) |> Map.ofArray [ while not sr.EndOfStream do let l = sr.ReadLine().Trim() match caseMap.TryFind l with | Some c -> yield c | None -> failwith <| "Could not find keyword: " + l ]
Wallace Kell.. 14
我找到了这个方便的代码片段......
open Microsoft.FSharp.Reflection let toString (x:'a) = match FSharpValue.GetUnionFields(x, typeof<'a>) with | case, _ -> 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
...这使得很容易将两行代码添加到任何DU ...
type A = X|Y|Z with override this.ToString() = FSharpUtils.toString this static member fromString s = FSharpUtils.fromString s
小智.. 8
我会像这样使用模式匹配:
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
也许在我的编辑器中第一次使用正则表达式自动生成匹配语句,但这只是因为你有数百个案例.但我不确定它是否比你更好的解决方案.
我找到了这个方便的代码片段......
open Microsoft.FSharp.Reflection let toString (x:'a) = match FSharpValue.GetUnionFields(x, typeof<'a>) with | case, _ -> 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
...这使得很容易将两行代码添加到任何DU ...
type A = X|Y|Z with override this.ToString() = FSharpUtils.toString this static member fromString s = FSharpUtils.fromString<A> s
由于案例没有价值,另一种选择是使用枚举:
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
然后你可以简单地使用Enum.Parse.
我会像这样使用模式匹配:
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
也许在我的编辑器中第一次使用正则表达式自动生成匹配语句,但这只是因为你有数百个案例.但我不确定它是否比你更好的解决方案.