You first need to recognise that it's a option, then you can match against the case. How about:

1
2
3
4
5
6
7
8
9
let encode (data: obj)=
    match data with
    | :? Option<_> as opt -> 
        match opt with
        | Some x -> printfn "%A" x
        | None -> printfn "None"
    | null -> printfn "null"
    | :? string -> printfn "string"
    | _ -> printfn "other"
By on 1/3/2009 10:51 PM ()

Oops. My tests failed. This is the sample I used

module test =
let aOpt = Some(100)
let a = 100
let isOption (x:obj) =
match x with
| :? Option<_> as opt -> true
| _ -> false
let u = isOption aOpt
let v = isOption a

after running the test, both u and v is false which should not be so.

Also, for the line " | :? Option<_> ... , the _ has the warning message
Warning 21 This construct causes code to be less generic than indicated by its type annotations. The type variable implied by the use of a '#', '_' or other type annotation at or near 'C:\Documents and Settings\Me\My Documents\Visual Studio 2008\Projects\GiKo\Somee\Tester.fs(10,20)-(10,21)' has been constrained to be type 'obj'.

I also realised that when I changed it from Option<_> to Option<int>, I had the correct result. The issue here is that the object can be of any type.

Thank you.

By on 1/4/2009 2:52 AM ()

Yes, it seems the code I suggested did not work. I think the problem is that kind of type comparison doesn't work well with generics. The code I wrote didn't produce a warning, I think this is a compiler bug.

I think the best option here is to use the F# reflection API, you could do a test using the function: Reflection.FSharpType.IsUnion and the get the union cases and check if there's a some and a none.

Cheers,

Rob

By on 1/5/2009 3:00 AM ()

Thanks.This is the final code I ended up with. It uses reflection just as you said.

///Determines if a given value is an option. None is interpreted as null
let isOption x =
match box x with
| null -> false
| _ ->
match FSharpType.IsUnion <| x.GetType() with
| true ->
FSharpType.GetUnionCases <| x.GetType()
|> Seq.exists (fun t->t.Name="Some" || t.Name="None")
| _ -> false
///Gets the value of an option. The value is returned if the type is not an option
let optionValue x =
match isOption x with
| true ->
let _,v = FSharpValue.GetUnionFields(x,x.GetType())
v.[0]
| _ -> x

By on 1/5/2009 12:56 PM ()

If I recall correctly, Option uses null to encode None.

By on 1/7/2009 7:44 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper