出于调试目的,我需要更多关于浮点数的详细信息,而不是box
给出的,并且我的所有测试代码都是通用的。所以我认为我Result<_, _>
并匹配类型以获得有意义的输出。
但是,类型可以是选项类型或// Illustrative example of what I'm trying to achieve (I think)
let rec mkStr v =
match box v with
| :? double as dbl -> Str.fromFloat dbl
| :? int64 as i -> i.ToString()
| _ ->
match v :> obj with
| :? Result<_, _> as res -> // this will never succeed
match res with
| Success s -> mkStr s
| Fail _ -> "Fail"
| x ->
x.ToString()
类型(成功/失败)。当你把它们当作有区别的联合对象时,这些类型只是模式匹配,但如果我对它们进行打字测试,它们就不会被击中:
Success
我尝试了各种拳击/拆箱/铸造,以上就是这些品种之一。当我调试时,我可以清楚地看到Result
正在通过,调试器甚至不会显示它是Success
。我知道DU中的每个鉴别器本身都是一个类型,所以我理解发生了什么,但我怎么能告诉编译器&#34;将其视为&#34;如果它看到它与Fail
或printf "%A"
TLDR:给定一个通用类型,如果有的话,如何测试并将类型转换为基础DU?
(PS:我意识到这通常不是杜鹃的方式,但就像{{1}}存在一样,我认为偶尔需要这样做,就像在这种情况下一样)
答案 0 :(得分:3)
使用引用来获得@kvb在评论中发布的模式匹配支持的解决方案是一个很好的技巧。我过去遇到了类似的问题并使用了一个稍微不同的技巧 - 而不是使用反射来解构和检查值,您可以使用反射来调用具有正确类型参数的泛型方法。这是一个最小的例子:
type MakeString =
static member Make<'T>(o:'T) =
match box o with
| :? float as f -> sprintf "Float: %A" f
| o ->
if typeof<'T>.Name = "FSharpOption`1" then
let tys = typeof<'T>.GetGenericArguments()
typeof<MakeString>.GetMethod("MakeOption")
.MakeGenericMethod(tys).Invoke(null, [| o |]) :?> string
else
failwith "Unknown"
static member MakeOption<'T>(o:option<'T>) =
match o with
| None -> "None"
| Some v -> "Some " + MakeString.Make(v)
MakeString.Make(Some 3.14)
如果Make
的某个option<'T2>
的某个'T2
类型的值被我们无法静态地知道,那么我们会通过查看通用内容来查找'T2
使用反射输入类型参数然后我们用MakeOption
作为类型参数调用'T2
- 所以在MakeOption
内,我们现在(再次)知道选项中包含的值的静态类型。
这样做的一个可能的优点是它都可以使用静态类型,因此当值表示为null
时它将自由工作(因此直接调用None.GetType()
会引发异常) 。 previous answer posted by @kvb也处理这个问题,但在这种情况下使用特殊情况。