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

烂漫一生 提交于 2019-12-19 08:30:41

问题


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?


回答1:


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 


来源:https://stackoverflow.com/questions/28538106/generic-f-function-how-to-get-the-type-of-an-f-discriminated-union

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!