简体   繁体   English

通用F#功能:如何获取F#鉴别联盟的类型?

[英]Generic F# function: How to get the Type of an F# Discriminated Union?

Code example: http://www.tryfsharp.org/create/dutts/Generics.fsx 代码示例: 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. 我在F#中有一些映射代码,它接受一个C#对象并将其包装在一个有区别的联合中。

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 这适用于第一次调用,但如果我尝试将它用于MyModule.MappedStuff类型,它会抱怨

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. 我尝试过使用静态解析的类型参数^ T,但是类型<^ T>抱怨。

I was thinking I could get this to work if I could somehow pass the "Type" (if that's the correct term, eg MyModule.Mapped) as a parameter but I don't know how to get that programmatically. 如果我能以某种方式将“类型”(如果这是正确的术语,例如MyModule.Mapped)作为参数传递,但我不知道如何以编程方式获取它,我以为我可以让它工作。

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. 我认为你为Makeunion的第二个参数引入的附加拳击Makeunion类型推断抛出轨道,事实上,该函数不再是通用的。 Either annotate the argument or remove the box . 注释参数或删除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 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM