open Microsoft.FSharp.Reflection
let toString (x:'a) =
match FSharpValue.GetUnionFields(x, typeof<'a>) with
| case, _ -> case.Name
let fromString<'a> (s:string) =
match FSharpType.GetUnionCases typeof<'a> |> Array.filter (fun case -> case.Name = s) with
|[|case|] -> Some(FSharpValue.MakeUnion(case,[||]) :?> 'a)
|_ -> None
// Usage:
// type A = X|Y|Z with
// member this.toString = toString this
// static member fromString s = fromString s
// > X.toString;;
// val it : string = "X"
// > A.fromString "X";;
// val it : A option = Some X
// > A.fromString "W";;
// val it : A option = None
// > toString X;;
// val it : string = "X"
// > fromString "X";;
// val it : A option = Some X