Beginner in F# here
I want to create a type, which is a sequence of another concrete type (Event) with at least one element. Any other elements can be added anytime later. Normally in C# I would create a class with a private List<Event> and public methods.
But I want to do it with a functional approach and not imitate the C# approach. Or at least try.
My train of thought:
Let's create a type "of seq" and give it a constructor requiring instance of the Event type
type Event = Event of string type PublishedEvents = EventList of seq<Event> with static member create (event:Event) = EventList(Seq.singleton event)
Now let's add an "add" method for adding another optional Event instances
type PublishedEvents with member this.add(event:Event) = Seq.append this [event]
But that doesn't work, F# complains that "this" is not compatible with seq<'a>.
So I tried this:
type PublishedEvents with member this.add (event:Event) : PublishedEvents = EventList(Seq.append this [event])
Now it complains that "this" is not compatible with seq<Event>...which is confusing me now since few lines above it says
EventList of seq<Event> ... so I guess I need to somehow convert
EventList back to
seq<Event> so I can then use
let convertFunction (eventList:PublishedEvents) : seq<Event> = ???
But I have no idea how to do this.
Am I even going the right direction? Is it better for this to mimic a C# class with a backing field? Or am I missing something?
I propose that you go even more functional and not create members for your types - have it done in your functions. For example this would achieve the same and I would argue it's more idiomatic F#:
type Event = Event of string type PublishedEvents = EventList of Event * Event list let create e = EventList (e,) let add (EventList(head,tail)) e = EventList(e,head::tail) let convert (EventList(head,tail)) = head::tail |> Seq.ofList let myNewList = create (Event "e1") let myUpdatedList = add myNewList (Event "e2") let sequence = convert myUpdatedList
val sequence : seq = [Event "e2"; Event "e1"]
On the other hand if your aim is to interop with C# your approach would be easier to consume on C# side.