Saturday, December 8, 2018

F# typed tuples and how to pattern match them


Noticed a warning fly-by in the compiler log in Visual Studio
warning FS0026: This rule will never be matched

When I opened the location that it complained about I saw the following code from my main event reducer:
let HandleEvent (state:State) (event:ApplicationEvent) : State =
 match event with 
 | ApplicationEvent (h, p) -> 
  {
   CurrentPlayer = CurrentPlayerReducer.HandleEvent state h p
   LastEventId = Some h.Id
   Timestamp = h.Timestamp
   PlayerStore = PlayerReducer.HandleEvent state.PlayerStore h p
   SpaceBodyStore = SpaceBodyReducer.HandleEvent state.SpaceBodyStore h p
  }
 | _ -> state

The warning was that the _ -> state rule will never match and I started to wonder if there might be a better way to write this thing.
The ApplicationEvent is defined as follows:
type ApplicationEvent = ApplicationEvent of EventHeader * obj
For those of you that have read my previous posts about Event Sourcing in F# may notice that the event definition has evolved a little bit since my last post in that series, no worries, I will post more when I have something working.

As you can see the ApplicationEvent type is pretty much just a discriminated union of 1 that has a named tuple.
This all makes it easy to handle the application event in the system as one object but when you want to look at the header and payload separately you will have to pattern match it to extract its parts, hence the pattern matching in the function above.

After a little bit of thinking I tried the following instead:
let HandleEvent (state:State) (ApplicationEvent (h, p)) : State =
 {
  CurrentPlayer = CurrentPlayerReducer.HandleEvent state h p
  LastEventId = Some h.Id
  Timestamp = h.Timestamp
  PlayerStore = PlayerReducer.HandleEvent state.PlayerStore h p
  SpaceBodyStore = SpaceBodyReducer.HandleEvent state.SpaceBodyStore h p
 }
I.e. I pattern match already in the in parameters to the function and thus get rid of the whole match construct in the function, and it works!
A day when you learn something new is not a wasted day!

So hope this helps someone out there!