F# Phantom Typing
The idea is that you will have a generic wrapper Event<'T>
and use different types for 'T
to represent different types of Events. These types (referring to 'T
) are never actually instantiated, which is why they’re called phantom types.
1[<Struct>]2type Event<'T> = Event of string3
4type ClickEvent = interface end5type KeyEvent = interface end6
7// Now we can create events of different types using the phantom types:8let createClickEvent (data: string) : Event<ClickEvent> = Event(data)9let createKeyEvent (data: string) : Event<KeyEvent> = Event(data)10
11// The nice thing about this is that we can write functions that work12// with any event easily:13let logEvent (Event data) = printfn "Event data: %s" data14
15// For example, I can now create one click event, one key event, and16// log both:17let clickEvent = createClickEvent "Click on button"18let keyEvent = createKeyEvent "Press 'Enter' key"19
20logEvent clickEvent21logEvent keyEvent22
23// However, trying to mix or compare events of different types will24// result in a compile-time error:25
26// This line will not compile because clickEvent and keyEvent have27// different phantom types.28let result = clickEvent = keyEvent