Lesson 10: Coercible

Contents
  • Enter Coercible
  • What can be coerced?
  • Updating the display function
  • Type applications
  • Coercibility is transitive
  • Coercion via type parameters
  • Coercing functions

In the previous lesson, we wrote this function:

errorCoerce :: Error -> [String]
errorCoerce (Error err) = err

We could envision having to write a lot of these, which would quickly get tiresome.

passwordCoerce :: Password -> String
passwordCoerce (Password x) = x

usernameCoerce :: Username -> String
usernameCoerce (Username x) = x

This is the kind of annoyance that hasn’t come up in this course because the examples have been small enough (we’ve only defined three newtypes), but can easily become a problem in a large codebase.

It gets worse if we have newtypes for other newtypes. Suppose our system has two kinds of login – normal users and administrative users – and we want to distinguish the password of an ordinary user from the password of an administrator, perhaps because we’re going to impose more stringent validation rules on administrator accounts.

newtype UserPW = UserPW Password

newtype AdminPW = AdminPW Password

We might want one set of “unwrappers” to convert each of these to Password

userPasswordCoerce :: UserPW -> Password
userPasswordCoerce (UserPW pw) = pw

adminPasswordCoerce :: AdminPW -> Password
adminPasswordCoerce (AdminPW pw) = pw

And then we may additionally want functions that unwrap both layers to get all the way down to the String.

userPasswordCoerce' :: UserPW -> String
userPasswordCoerce' = passwordCoerce . userPasswordCoerce

And we’d probably also like a composition of the constructors to coerce in the other direction as well.

userPasswordCoerceBack :: String -> UserPW
userPasswordCoerceBack = UserPW . Password

This will get tiresome very quickly. Fortunately, GHC has a function called coerce that can take the place of all of these conversions, and that’s what this lesson is about.

Sign up for access to the full page, plus the complete archive and all the latest content.