You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

参数类型一致的F#联合类型:如何通过构造函数获取UnionCaseInfo?

问题描述

我们定义了一个包含3个分支的联合类型(DU),每个分支都以Object类型作为参数:

type DU =
    | X of Object
    | Y of Object
    | Z of Object

已知FSharp.Reflection.FSharpType命名空间中的GetUnionCases函数,传入DU的类型信息后可返回UnionCaseInfo数组。

我们希望实现一个函数f: ('T -> DU) -> UnionCaseInfo,满足:

  • f X 返回分支X对应的UnionCaseInfo
  • f Y 返回分支Y对应的UnionCaseInfo
  • 以此类推

由于当前所有分支的参数类型都是Object(多对一映射),此前的两种常规方法都不适用:

  • 若DU分支无参数,可通过typeof<DU>的GetProperties()获取单例实例关联对应UnionCaseInfo
  • 若各分支参数类型不同,可通过构造函数的Invoke方法的类型关联分支

请问这个需求是否可行?

可行方案

可行,核心思路是利用独特标记对象结合联合类型的反射解析来区分分支:

  1. 创建一个唯一的标记类型(避免和其他Object类型冲突):
type Marker() = class end
let marker = Marker()
  1. 实现函数f:传入分支构造函数时,先用标记对象构造一个DU实例,再通过FSharpValue.GetUnionFields解析该实例,提取对应的UnionCaseInfo:
open FSharp.Reflection

let f (ctor: obj -> DU) =
    let duInstance = ctor marker
    let unionCase, _ = FSharpValue.GetUnionFields(duInstance, typeof<DU>)
    unionCase
  1. 验证使用:
// 获取各分支的UnionCaseInfo
let xCase = f X
let yCase = f Y
let zCase = f Z

// 输出分支名称验证
printfn "%s" xCase.Name // 输出 "X"
printfn "%s" yCase.Name // 输出 "Y"
printfn "%s" zCase.Name // 输出 "Z"

原理说明

每个分支的构造函数会用标记对象生成对应分支的实例,FSharpValue.GetUnionFields可以直接从实例中提取出其所属的UnionCaseInfo,完全不需要依赖参数类型的差异。标记对象仅用于临时构造实例,不会影响业务逻辑,且因为是自定义类型,不会和其他可能传入的Object类型混淆。


内容的提问来源于stack exchange,提问作者RMills330

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 06:27:16