F# support
Opened this issue · 4 comments
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
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"
as an interim, maybe look at Chiron's combinator-based model and have a Chiron 'backend' for Serde.ISerialize
and Serde.IDeserialize
instances?
This issue was kind of DoA, but now I'm curious.
-
Wouldn't that still involve generating the Chiron
FromJson
andToJson
static methods?
If so, why not just generate using theSerializeField
method as above and avoid the extra dependency? -
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.)
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.