Skip to content

Instantly share code, notes, and snippets.

@ninjazoete
Last active September 3, 2017 19:37
Show Gist options
  • Save ninjazoete/4f3911ded4f717ed5a91f4518d8e788a to your computer and use it in GitHub Desktop.
Save ninjazoete/4f3911ded4f717ed5a91f4518d8e788a to your computer and use it in GitHub Desktop.
Using phantom types in order to let the type system guard us against unvalidated data
//: Playground - noun: a place where people can play
import Cocoa
// Phantom Types Example
struct Validated {}
struct Unvalidated {}
struct Form<T> {
// Implicitly unwrapped optionals - when anyone uses a validated form he trusts the type that it is filled with data
var destination: String!
var date: Date!
}
// Factory for form
func initialForm() -> Form<Unvalidated> {
return Form<Unvalidated>(destination: "", date: Date())
}
func validate(form: Form<Unvalidated>) -> Optional<Form<Validated>> {
// If it is okay return
return Optional.some(Form<Validated>(destination: "", date: Date()))
// else
return Optional.none
}
// API that does use validated forms. It is type proof
func fetchResults(forForm form: Form<Validated>, completion: ((Void) -> Void)) {
// Form must be correct as the phantom type is Validated.
// Use form to fetch data and omit checks / preconditions
// In such APIs where input is Form<Validated> down the road
// you can forget that form can be incorrectly filled.
completion()
}
// -----------
// Usage
// -----------
// Initialize starting form
var form = initialForm()
// Fill its data
form.destination = "ABCD"
form.date = Date()
// Validate the form
validate(form: form).map { validatedForm in
// and use it in any API that requires a Form<Validated> parameter
fetchResults(forForm: validatedForm, completion: {})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment