泛型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(找到,[| box external |]):?> 'T
我试图像这样使用它:
let testThings = toDomain< MyModule.MappedThings> doExternalThings
let testStuff = toDomain< MyModule.MappedStuff> doExternalStuff
这对第一次调用来说很好,但是如果我尝试将它用于MyModule.MappedStuff类型它抱怨
这个表达式应该有DoThings类型,但是这里有类型DoStuff
我试过使用静态解析的类型参数,^ T,但是输入< ^ T>抱怨。
我想我可以得到这个工作,如果我能以某种方式通过类型(如果这是正确的术语,例如MyModule.Mapped)作为参数,但我不知道如何以编程方式。
任何人都可以帮忙吗?
您为> Makeunion
的第二个参数引入的装箱会将类型推断抛出轨道,事实上,函数不再是通用的。注释参数或移除框
。
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
Code example: http://www.tryfsharp.org/create/dutts/Generics.fsx
I have some mapping code in my F# which takes a C# object and wraps it in a discriminated union.
module MyModule =
type MappedThings =
| DoThings of External.Things.DoThings
type MappedStuff =
| DoStuff of External.Stuff.DoStuff
As I always use the same name in my discriminated union as the external object I would like to try to make my mapping code generic for scalability. This is what I've tried so far:
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
I am trying to use it like this:
let testThings = toDomain<MyModule.MappedThings> doExternalThings
let testStuff = toDomain<MyModule.MappedStuff> doExternalStuff
This works fine for the first call, but if I try to use it for MyModule.MappedStuff type it complains with
This expression was expected to have type DoThings but here has type DoStuff
I've tried using statically resolved type parameters, ^T, but the typeof<^T> complains.
I was thinking I could get this to work if I could somehow pass the "Type" (if that's the correct term, e.g. MyModule.Mapped) as a parameter but I don't know how to get that programmatically.
Can anyone help?
I think that the additional boxing that you introduce for the 2nd parameter of Makeunion
throws the type inference off the track and in fact, the function isn't generic anymore. Either annotate the argument or remove the 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
这篇关于泛型F#函数:如何获取F#歧视联盟的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!