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

F# support #36

Open
JordanMarr opened this issue Oct 1, 2021 · 4 comments
Open

F# support #36

JordanMarr opened this issue Oct 1, 2021 · 4 comments

Comments

@JordanMarr
Copy link

JordanMarr commented Oct 1, 2021

After playing around with the C# implementation, I was thinking about what an F# implementation might look like using Myriad:

C#

[GenerateSerialize]
public partial class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
public partial class Person : Serde.ISerialize
{
    void Serde.ISerialize.Serialize(ISerializer serializer)
    {
        var type = serializer.SerializeType("Person", 2);
        type.SerializeField("Name", new StringWrap(Name));
        type.SerializeField("Age", new Int32Wrap(Age));
        type.End();
    }
}

F#

[<GenerateSerialize>]
type Person = 
    {
        Name: string
        Age : int
    }

Generated:

module Person

let toSerializable (person: Person) =
    { new Serde.ISerialize with
        member this.Serialize(serializer: ISerializer) = 
            let type = serializer.SerializeType("Person", 2)
            type.SerializeField("Name", StringWrap(person.Name))
            type.SerializeField("Age", Int32Wrap(person.Age))
            type.End() 
    }

Usage:

{ Name = "John"; Age = 100 }
|> Person.toSerializable
|> JsonSerializer.Serialize
|> printfn "%s"

It wouldn't be quite as user friendly as the C# generator version because:

  • User would be required to manually include generated output file in the .fsproj file
  • Possible .toml config file needed
  • Myriad NuGet package required
@JordanMarr
Copy link
Author

JordanMarr commented Oct 1, 2021

Or maybe:

Generated:

module Person

let serializeWith (serializeFn: Serde.ISerialize -> string) (person: Person) =
    { new Serde.ISerialize with
        member this.Serialize(serializer: ISerializer) = 
            let type = serializer.SerializeType("Person", 2)
            type.SerializeField("Name", StringWrap(person.Name))
            type.SerializeField("Age", Int32Wrap(person.Age))
            type.End() 
    }
    |> serializeFn

Usage:

{ Name = "John"; Age = 100 }
|> Person.serializeWith (JsonSerializer.Serialize)
|> printfn "%s"

@baronfel
Copy link

as an interim, maybe look at Chiron's combinator-based model and have a Chiron 'backend' for Serde.ISerialize and Serde.IDeserialize instances?

@JordanMarr
Copy link
Author

JordanMarr commented Dec 10, 2023

This issue was kind of DoA, but now I'm curious.

  1. Wouldn't that still involve generating the Chiron FromJson and ToJson static methods?
    If so, why not just generate using the SerializeField method as above and avoid the extra dependency?

  2. Do you think there is enough interest in F# community (now that net8 is out) to warrant adding F# support for this library?

EDIT: It just occurred to me that you were suggesting Chiron as an already-existing alternative.
(Question 2 still applies though.)

@agocke
Copy link
Collaborator

agocke commented Dec 10, 2023

FWIW I'm still thinking about this and exactly how to implement it. The main hold-up is that I'm still iterating a bit on the Serde API itself.

For example, right now ISerialize implicitly uses the this parameter as the value, meaning that wrappers also require implementing the IWrapper type to be composable. This original API made sense in the context of languages with type classes (like Rust) because you could add support as an extension and the receiver would implicitly flow into your extension. But it's kind of obnoxious in C#. I've been bitten a few times by forgetting to implement IWrapper and then being stuck when trying to add composition.

So I think I might make ISerialize generic and add the value to the Serialize call. This will require changing the source generator, but that's not a big deal right now. When I add more F# support then I'll have to change Myriad as well, so there's a lot more iteration work. I'm waiting until I'm pretty sure the API's stable fore making more work for myself.

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

3 participants