
Suppose I need to represent a user in a database. I could make a table like this one (using Yesod's config/models syntax): User name Text email Text Maybe is_verified Bool default=false last_login UTCTime default=now() Instead, it would be better to do the following, so I couldn't swap name and email by accident or feed a wrong value to is_verified and last_login: User name UserName email UserEmail v Maybe last_login UserLastLogin where newtype UserName = UserName Text deriving (Show, Read) derivePersistField "UserName" newtype UserLastLogin = UserLastLogin UTCTime deriving (Show, Read) derivePersistField "UserLastLogin" data Verified data Unverified newtype UserEmail v = UserEmail Text deriving (Show, Read) derivePersistField "UserEmail" (So I could define functions like sendAnnouncement :: UserEmail Verified -> IO () sendVerification :: UserEmail Unverified -> IO ()) The Haskell part is not new and has been successfully used in the large (see http://code.haskell.org/~dons/talks/dons-google-2015-01-27.pdf, pp. 17--21), but I wonder whether it's reasonable in the database layer. The first table will be mapped to this in PostgreSQL: User name character varying not null email character varying is_verified boolean not null default false last_login timestamp with time zone not null default now() while the second will use character varying for everything. The only downsides of the latter approach I can think of: 1. You can no longer rely on the database to ensure (basic) type safety, so everything needs to be done in the Haskell layer. Otherwise, you will get runtime errors. 2. I haven't benchmarked this, but I assume that comparing, say, booleans should be faster than comparing varchars. So, is it worth it in practice? Do I need to worry about these issues? And are there any other problems?