F#: How do I convert Option<'a> to Nullable, also when 'a can be System.String?

Viewed 59

When converting F# option values to C# nullables for interop, I have to use two different functions, depending on the whether the I'm dealing with an Option of a string or option of a struct type:

module Option =
   (* Does not work for strings *)
   let toNullable (aO : Option<'a>) =
      match aO with
      | None   -> System.Nullable<_>()
      | Some a -> System.Nullable<_>(a)   

   (* does not work for integers and other struct types *)
   let string_toNullable (aO : Option<string>) =
      match aO with
      | Some s -> s
      | None -> null

Is there a way to check the type of the option at runtime in order to obtain one function that always works? All my attempts run into errors, such as:


   (* The type 'Option<'a>' does not have any proper 
      subtypes and cannot be used as the source of a
      type test or runtime coercion. *)
   let toNullable2 (aO : Option<'a>) =
      match aO with
      | :? Option<System.String> -> ... 


   (* This runtime coercion or type test from type 'a to System.String involves
      an indeterminate type based on information prior to this program point.
      Runtime type tests are not allowed on some types.
      Further type annotations are needed. *)
   let toNullable2 (aO : Option<'a>) =
      match aO with
      | Some a -> match a with | :? System.String -> ...


   (* Type constraint mismatch.
      The type 'System.Nullable<obj>' is
      not compatible with type 'System.String' *)
   let toNullable2 (aO : Option<obj>) =
      match aO with
      | Some a ->
         match a with
         | :? System.String as s -> s
         | _ -> System.Nullable<_>(a)

Thank you

Roland

1 Answers

After some further reading and thinking I'm pretty sure the above is not possible, since System.String is a different type than System.Nullable.

For my purposes I have found a solution, which looks as follows:

   let toNullOrObj aO =
      match aO with
      | None -> null
      | Some x -> box x

This works for me because the downstream code (Google's sheets API) wants an obj anyway.

Related