通用 F# 函数:如何获取 F# 区分联合的类型?
Generic F# function: How to get the Type of an F# Discriminated Union?
代码示例:http://www.tryfsharp.org/create/dutts/Generics.fsx
我的 F# 中有一些映射代码,它采用 C# 对象并将其包装在可区分的联合中。
module MyModule =
type MappedThings =
| DoThings of External.Things.DoThings
type MappedStuff =
| DoStuff of External.Stuff.DoStuff
因为我总是在我的可区分联合中使用与外部对象相同的名称,所以我想尝试使我的映射代码通用以实现可伸缩性。这是我到目前为止尝试过的:
let toDomain<'T> external : 'T =
let found = FSharpType.GetUnionCases(typeof<'T>) |> Seq.where (fun t -> t.Name = external.GetType().Name) |> Seq.head
FSharpValue.MakeUnion(found, [| box external |]) :?> 'T
我正在尝试这样使用它:
let testThings = toDomain<MyModule.MappedThings> doExternalThings
let testStuff = toDomain<MyModule.MappedStuff> doExternalStuff
这在第一次调用时工作正常,但如果我尝试将它用于 MyModule.MappedStuff 类型,它会抱怨
This expression was expected to have type DoThings but here has type DoStuff
我试过使用静态解析的类型参数 ^T,但 typeof<^T> 报错。
我想如果我能以某种方式将 "Type"(如果这是正确的术语,例如 MyModule.Mapped)作为参数传递,我就可以让它工作,但我不知道如何以编程方式获取。
有人能帮忙吗?
我认为您为 Makeunion
的第二个参数引入的额外装箱会使类型推断偏离轨道,事实上,该函数不再是通用的。注释参数或删除 box
.
let toDomain<'T> external : 'T =
let found = FSharpType.GetUnionCases(typeof<'T>) |> Array.find (fun t -> t.Name = external.GetType().Name)
FSharpValue.MakeUnion(found, [| external |]) :?> 'T
代码示例:http://www.tryfsharp.org/create/dutts/Generics.fsx
我的 F# 中有一些映射代码,它采用 C# 对象并将其包装在可区分的联合中。
module MyModule =
type MappedThings =
| DoThings of External.Things.DoThings
type MappedStuff =
| DoStuff of External.Stuff.DoStuff
因为我总是在我的可区分联合中使用与外部对象相同的名称,所以我想尝试使我的映射代码通用以实现可伸缩性。这是我到目前为止尝试过的:
let toDomain<'T> external : 'T =
let found = FSharpType.GetUnionCases(typeof<'T>) |> Seq.where (fun t -> t.Name = external.GetType().Name) |> Seq.head
FSharpValue.MakeUnion(found, [| box external |]) :?> 'T
我正在尝试这样使用它:
let testThings = toDomain<MyModule.MappedThings> doExternalThings
let testStuff = toDomain<MyModule.MappedStuff> doExternalStuff
这在第一次调用时工作正常,但如果我尝试将它用于 MyModule.MappedStuff 类型,它会抱怨
This expression was expected to have type DoThings but here has type DoStuff
我试过使用静态解析的类型参数 ^T,但 typeof<^T> 报错。
我想如果我能以某种方式将 "Type"(如果这是正确的术语,例如 MyModule.Mapped)作为参数传递,我就可以让它工作,但我不知道如何以编程方式获取。
有人能帮忙吗?
我认为您为 Makeunion
的第二个参数引入的额外装箱会使类型推断偏离轨道,事实上,该函数不再是通用的。注释参数或删除 box
.
let toDomain<'T> external : 'T =
let found = FSharpType.GetUnionCases(typeof<'T>) |> Array.find (fun t -> t.Name = external.GetType().Name)
FSharpValue.MakeUnion(found, [| external |]) :?> 'T