Search code examples
genericsf#c#-to-f#valuetuple

F# generics generic construct requires that the type 'struct (Guid * int)' have a public default constructor


I have a interface in C# with method with this return type:

Task<(Guid, int)?>

I need to implement this interface in F# and if I am not mistaken this should be equivalent in F#:

Task<Nullable<ValueTuple<Guid, int>>>

Unfortunately when I compile I get this message:

generic construct requires that the type 'struct (Guid * int)' have a public default constructor

I have found some similar questions and looks like solution is usage of [<CLIMutable>] attribute. But that's not something what I can do with System.ValueTuple. Is there a way to use Nullable ValueTuple in F#?


Solution

  • I think this is a compiler bug in F#. You might want to open an issue on the F# GitHub page and report this behavior. The reason I suspect it is a compiler bug is that I can make it work by simply unboxing struct (System.Guid, int) to ValueTuple<System.Guid, int>, which should already be equivalent types. Here's how I made it work in a sample, which may serve as a viable workaround for you as well, until someone more familiar with the F# compiler can let you know if it is a genuine bug or not:

    open System
    open System.Threading.Tasks
    
    type ITest =
        abstract member F: unit -> Task<Nullable<ValueTuple<Guid, int>>>
    
    type T () =
        interface ITest with
            member __.F () =
                let id = Guid.NewGuid()
                let x = Nullable(struct (id, 0) |> unbox<ValueTuple<Guid, int>>)
                Task.Run(fun () -> x)
    
    (T() :> ITest).F().Result