Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample deserialise union? #14

Closed
haf opened this issue Apr 18, 2015 · 6 comments
Closed

Sample deserialise union? #14

haf opened this issue Apr 18, 2015 · 6 comments

Comments

@haf
Copy link
Contributor

haf commented Apr 18, 2015

You have a serialise example; could you show the deserialise example?

type TestUnion =
    | One of string
    | Two of int * bool

    static member ToJson (x: TestUnion) =
        match x with
        | One (s) -> Json.write "one" s
        | Two (i, b) -> Json.write "two" (i, b)
@haf
Copy link
Contributor Author

haf commented Apr 20, 2015

So, no answer, eh? That meant I had to think for myself. Evil you!

I might have a few options... The active pattern in particular makes it very F#.

Alternative 1, pattern matching, vanilla:

    static member FromJson (_ : TestUnion) =
      Json.tryRead "one"
      >>= (function
          | Some s -> Json.init (One s)
          | None   -> Json.read "two" |> Json.map Two)

Alternative 2, effing functional:

    static member FromJson (_ : TestUnion) =
      Json.tryRead "one"
      >>= Option.fold (fun s t -> Json.init (One t)) (Json.read "two" |> Json.map Two)

Alternative 3, wooorkflows:

    static member FromJson (_ : TestUnion) =
      json {
        let! mone = Json.tryRead "one"
        match mone with
        | Some s -> return One s
        | None ->
          let! x = Json.read "two"
          return Two x
      }

My favorite, the active pattern variant:

    static member FromJson (_ : TestUnion) =
      function
      | Prop "one" str as json ->
        Json.init (One str) json
      | Prop "two" (i, b) as json ->
        Json.init (Two (i, b)) json
      | json ->
        Json.error (sprintf "couldn't deserialise %A to TestUnion" json) json

Using this discriminated union:

let inline (|Prop|_|) key =
  Lens.getPartial (objectKeyPLens key)
  >> Option.bind Json.tryDeserialize

haf added a commit to haf/chiron that referenced this issue Apr 20, 2015
@kolektiv
Copy link
Member

Ah, I have been off-grid for a few days, rather than employing any kind of socratic silence :) Back now though! I would personally probably go for something like alternative 1. Although I'm just going to have a quick play with a different idea...

@kolektiv
Copy link
Member

Hmmm. Looking at it more now I think that the active pattern variant is objectively the "best" as it'll scale much better to unions with N cases, the others become unwieldy (as would my other idea). I wonder if we can sensible include that active pattern in the library (called something like ObjectKey or something perhaps?)

I think that works nicely...

@haf
Copy link
Contributor Author

haf commented Apr 20, 2015

Cool, we agree then! =) I have a DU with about 25 cases I need this for ;)

I believe they're called 'properties' in JS lang?

@kolektiv
Copy link
Member

I'm not sure I've seen much consistency! "Property" would be cool i think,
provided it isn't one of the uncountable f# reserved keywords...

On 20 April 2015 at 22:24, Henrik Feldt notifications@github.com wrote:

Cool, we agree then! =) I have a DU with about 25 cases I need this for ;)

I believe they're called 'properties' in JS lang?


Reply to this email directly or view it on GitHub
#14 (comment).

@kolektiv
Copy link
Member

I've included the "Property" pattern in the pull request #30 (combined changes). It's a neat little addition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants