RSS Feed David on GitHub David on LinkedIn David on Medium David on Twitter

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.

phantom-typing.fs
1
[<Struct>]
2
type Event<'T> = Event of string
3
4
type ClickEvent = interface end
5
type KeyEvent = interface end
6
7
// Now we can create events of different types using the phantom types:
8
let createClickEvent (data: string) : Event<ClickEvent> = Event(data)
9
let createKeyEvent (data: string) : Event<KeyEvent> = Event(data)
10
11
// The nice thing about this is that we can write functions that work
12
// with any event easily:
13
let logEvent (Event data) = printfn "Event data: %s" data
14
15
// For example, I can now create one click event, one key event, and
16
// log both:
17
let clickEvent = createClickEvent "Click on button"
18
let keyEvent = createKeyEvent "Press 'Enter' key"
19
20
logEvent clickEvent
21
logEvent keyEvent
22
23
// However, trying to mix or compare events of different types will
24
// result in a compile-time error:
25
26
// This line will not compile because clickEvent and keyEvent have
27
// different phantom types.
28
let result = clickEvent = keyEvent