Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dynamically determine type of Option when it has value 'None'

Tags:

optional

f#

There is some difficulty in getting Option type dynamically. Suppose I have a function:

let printType x =
   if (box x) = null then printfn "the type is 'null'"
   else printfn "the type is %A" (x.GetType())

And we have the output here:

printType 3          // the type is System.Int32
printType (Some(3))  // the type is Microsoft.FSharp.Core.FSharpOption`1[System.Int32]
printType None       // the type is null
printType null       // the type is null

How to differentiate between None and null when getting an expression's type?

like image 276
Oleg Leonov Avatar asked Feb 18 '14 13:02

Oleg Leonov


2 Answers

At runtime, option None values are represented as null and so you cannot determine their runtime type. However, you could write a generic function that prints the static type of the option:

let printType (x:'T option) =
  printfn "Static type is: %s" (typeof<'T>.Name)

Depending on what you need, this might or might not do what you need.

printType (None : int option)     // Int32
printType (None : string option)  // String 
printType None                    // Object (the default used by the inference)

EDIT If you want to be able to call the function on any arguments, you can use typeof<'T> as in my example together with the rest of the logic as in the solution by Matthew. The following does the same thing as Matthew's snippet (but it does not create quotations for no good reason):

let printType (x:'T) =
  let typeOfX = typeof<'T>
  if not <| FSharpType.IsUnion(typeOfX) && (box x) = null then 
    printfn "Static type is %s, but the value is 'null'" typeOfX.Name
  else 
    printfn "Static type is %s and value is not 'null'" typeOfX.Name
like image 80
Tomas Petricek Avatar answered Sep 21 '22 21:09

Tomas Petricek


Edit: The code quotation is not needed and typeof can be used instead, see @Tomas Petricek's answer

You could use a code quotation to get the type from None

open Microsoft.FSharp.Reflection

let printType x = 
    let typeOfX = <@ x @>.Type

    if not <| FSharpType.IsUnion(typeOfX) && (box x) = null then 
        printfn "the type is 'null'"
    else 
        printfn "the type is %A" typeOfX

Your input:

printType 3          // the type is System.Int32
printType (Some(3))  // the type is Microsoft.FSharp.Core.FSharpOption`1[System.Int32]
printType None       // the type is Microsoft.FSharp.Core.FSharpOption`1[System.Object]
printType null       // the type is 'null'
like image 3
Matthew Mcveigh Avatar answered Sep 18 '22 21:09

Matthew Mcveigh