gpt4 book ai didi

reflection - F# 可区分联合的拆箱值

转载 作者:行者123 更新时间:2023-12-01 12:19:52 25 4
gpt4 key购买 nike

即使键入了基础值,我的 F# 代码的某些函数也会接收作为对象装箱的值。如果该值是可区分联合,则无法将其拆箱回其 F# 类型。这是一个简单的例子:

type Result<'TOk,'TError> = 
| Ok of 'TOk
| Error of 'TError

type ResultA = Result<string, int>

let a = Ok "A"
let o = box a

match o with
| :? ResultA -> printfn "match ResultA"
// | :? ResultA.Ok -> printfn "match" // doesn't compile
| _ when o.GetType().DeclaringType = typedefof<ResultA> -> printfn "match via reflection"
| _ -> printfn "no match"

此示例的输出是“通过反射匹配”,ResultA 永远不会匹配,因为装箱值属于不同的 CLR 类型 - Result.Ok。由于 F# 区分的联合案例表示为其自己的类型,因此装箱值与 ResultA 类型不匹配。此外,无法将其与 ResultA.OK 匹配,因为在 F# 代码中它不是合法类型。唯一的选择似乎是使用反射手动实例化一个值,这是低效和愚蠢的,因为该值已经被实例化,它就在这里,一旦它被装箱就无法在 F# 代码中访问。

我是否忽略了什么?有没有更直接的方法来拆箱 F# 区分联合值?

最佳答案

你只是匹配不同的类型。您的变量 a不是类型 ResultA ,但属于泛型 Result<string, 'a> ,当装箱时被强制为 Result<string, obj> .

要么使变量显式具有正确的类型:

let a : ResultA = Ok "A"

或者匹配正确的类型:
match o with
| :? Result<string, obj> -> printfn "match ResultA"

这两个选项都有效。

关于您的假设的说明 :

ResultA is never matched because the boxed value is of a different CLR type - Result.Ok



这不是原因。与类型匹配的工作方式与 is 相同/ as C# 中的运算符 - 即它匹配子类型以及确切类型。并且 DU 成员被编译为 DU 类型本身的子类型。这就是 F# 如何让 .NET 将不同情况作为一种类型处理。

关于运行时输入的一般说明 :
不需要在运行时处理类型。如果可能的话,尽量避免它。经验法则应该是,如果您发现自己在运行时处理类型,那么您可能建模错误。

如果您不确切知道一切是如何工作的,则尤其如此。

关于reflection - F# 可区分联合的拆箱值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45237434/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com