F# sequence with at least one element

  • A+

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 Seq.append ?

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.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: