Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is F# aware of its discriminated unions' compiled forms?

A discriminated union in F# is compiled to an abstract class and its options become nested concrete classes.

type DU = A | B

DU is abstract while DU.A and DU.B are concrete.

With ServiceStack, the serialization of types to JSON strings and back can be customized with functions. With respect to the DU type, here's how I could do it in C#.

using ServiceStack.Text;

JsConfig<DU.A>.SerializeFn = v => "A"; // Func<DU.A, String>
JsConfig<DU.B>.SerializeFn = v => "B"; // Func<DU.B, String>
JsConfig<DU>.DeserializeFn = s =>
    if s == "A" then DU.NewA() else DU.NewB(); // Func<String, DU>

Is F# aware of its discriminated unions' compiled forms? How would I get the type of DU.A in F# at compile time?

typeof<DU> // compiles
typeof<DU.A> // error FS0039: The type 'A' is not defined
typeof<A> // error FS0039: The type 'A' is not defined

I can easily enough register a function for deserialization in F#.

open System
open ServiceStack.Text

JsConfig<DU>.RawDeserializeFn <-
    Func<_, _>(fun s -> printfn "Hooked"; if s = "A" then A else B)

Is it possible to register serialize functions wholly in F# for the concrete types DU.A and DU.B?

like image 307
philderbeast Avatar asked Jul 24 '13 11:07

philderbeast


1 Answers

Daniel is correct, you can do this by registering serialization functions for the base type DU. Here is a fuller example

open System
open ServiceStack.Text

type DU = A | B

let serialize = function
    | A -> "A"
    | B -> "B"

let deserialize = function
    | "A" -> A
    | "B" -> B
    | _   -> failwith "Can't deserialize"

JsConfig<DU>.SerializeFn <- Func<_,_>(serialize)
JsConfig<DU>.DeSerializeFn <- Func<_,_>(deserialize)

let value = [| A; B |]
let text = JsonSerializer.SerializeToString(value)
let newValue = JsonSerializer.DeserializeFromString<DU[]>(text)

Result:

val value : DU [] = [|A; B|]
val text : string = "["A","B"]"
val newValue : DU [] = [|A; B|]
like image 60
Leaf Garland Avatar answered Sep 30 '22 18:09

Leaf Garland