This episode is for subscribers only. To access it, and all past and future episodes, become a subscriber today!See subscription optionsorLog in
Sign up for our weekly newsletter to be notified of new episodes, and unlock access to any subscriber-only episode of your choosing!Sign up for free episode
We often work with types that are far too general or hold far too many values than what is necessary in our domains. In our past episode on algebraic data types we used algebra to help simplify certain types to chisel them down to their core essentials. However, sometimes that isn’t possible. Sometimes we just want to differentiate between two seemingly equivalent values at the type level.
For example, an email address is nothing but a string, but it should be restricted in the ways in which it can be used. Also, ids in our code may all be integers, but it doesn’t make sense to compare a user’s id with, say, a subscription id. They are completely different entities.
We want to show that Swift, and in particular Swift 4.1, gives us an incredible tool to lift types up to a higher level so that they can distinguished from each other more easily. This helps improve the contracts we are building into our functions and methods, and overall makes our code safer.
ExpressibleByStringLiteral in order to restore the ergonomics of initializing our
ExpressibleByStringLiteral requires a couple other prerequisite conformances.
Comparable and sort users by their
id in descending order.
Let’s explore what happens when you have multiple fields in a struct that you want to strengthen at the type level. Add an
age property to
User that is tagged to wrap an
Int value. Ensure that it doesn’t collide with
User.Id. (Consider how we tagged
Numeric and alias a tagged type to
Cents. Explore the ergonomics of using mathematical operators and literals to manipulate these values.
Create a tagged type,
Light<A> = Tagged<A, Color>, where
A can represent whether the light is on or off. Write
turnOff functions to toggle this state.
Write a function,
changeColor, that changes a
Light’s color when the light is on. This function should produce a compiler error when passed a
Light that is off.
Create two tagged types with
Double raw values to represent
Fahrenheit temperatures. Write functions
fahrenheitToCelsius that convert between these units.
Validated tagged types so that you can create a function that takes an
Unvalidated<User> and returns an
Optional<Validated<User>> given a valid user. A valid user may be one with a non-empty
name and an
Tagged is one of our open source projects for expressing a way to distinguish otherwise indistinguishable
types at compile time.
In this blog post we use the
Tagged type to provide a type safe way for
interacting with seconds and milliseconds values. We are able to prove to ourselves that we do not misuse
or mix up these values at compile time by using the tagged wrappers.
In this Swift Talk episode, Florian and special guest Brandon Kase show how to apply the ideas of phantom types to create a type safe API for dealing with file paths. We’ve used phantom types in our episode on Tagged to provide a compile-time mechanism for distinguishing otherwise indistinguishable types.