从字符串创建可区分的联合案例 [英] Create Discriminated Union Case from String

查看:18
本文介绍了从字符串创建可区分的联合案例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从字符串创建 DU 案例.我可以看到这样做的唯一方法是通过 Microsoft.FSharp.Reflection.FSharpType.GetUnionCases 枚举 DU 案例,然后选择与字符串匹配的 UnionCase(通过使用 .Name),然后使用 FSharpValue.MakeUnion 制作实际的 DU 案例.

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.GetUnionCases and then picking the UnionCase that matches the string (by using .Name) and then making the actual DU case out of that by using FSharpValue.MakeUnion.

难道没有更简单/更优雅的方法来做到这一点吗?在我的场景中,我有一个包含数百个关键字案例的 DU.我必须从文件中读取字符串(关键字)并从中提取类型.我通过将案例放入 Map 进行了一些优化",但我希望有更好的方法来做到这一点.

Isn't there an easier/more elegant way of doing this? In my scenario I have a DU with a couple of hundred cases for keywords. I have to read the strings (keywords) from a file and make the types out of them. I did some "optimization" by putting the cases into a Map but I was hoping there'd be a better way of doing this.

我有以下内容,例如:

type Keyword = 
    | FOO
    | BAR
    | BAZ
    | BLAH

let mkKeywords (file: string) =
    use sr = new StreamReader(file)

    let caseMap = 
        FSharpType.GetUnionCases(typeof<Keyword>)
        |> 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
    ] 

推荐答案

我发现了这个 方便的代码片段...

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

...这使得在任何 DU 上添加两行代码变得容易...

... 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

这篇关于从字符串创建可区分的联合案例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆