PureScript got field names right, Haskell got them wrong

🎉I am writing these notes at Brick, a magical mystery no-bullshit publishing platform. Turns out writing goes much faster when I don't have to hit “Publish” or do git commit.

You can use it too — check it out at Brick.do.


I had to dive into PureScript recently. I won't talk about row types, etc, but they got one thing super right. It's a small, but unambiguous, win.

In Haskell, field names have to be valid identifiers. Even something like type can not be a field name, thus leading people to add underscores.

data Entity = Entity
  { id :: String
  , _type :: EntityType
  , _Status :: Status
  , domainRole :: Role -- corresponds to "domain:role"
  }

It is convenient to use records as canonical specifications of the shape of your data — generating JSON schemas, Swagger docs, YAML parsers, etc, from them. And it is super annoying to have to deal with those corner cases.

In PureScript, on the other hand, field names can be literally anything. They can start with big letters. They can start with numbers. They can contain dots and exclamation marks. Anything you want.

And this is awesome for a simple stupid reason — when an external service designed twenty years ago throws horrible weird data at you, you'll be able to handle it without having to pick different names (and naming is the hardest thing in programming!).

newtype Entity = Entity
  { id :: String
  , type :: EntityType
  , "Status" :: Status
  , "domain:role" :: Role
  }

🤔In fact, I would take it one step further. String literals should be allowed in all identifiers, for compatibility with names defined elsewhere. What we get otherwise is horrible names like aCCESS_SYSTEM_SECURITY. (Though in this particular case a pattern synonym is a better solution anyway.)

😍Also see: Go's struct tags. They are awesome. Decorators might be awesomer still.

Though I still think unrestricted field names are good, since they will be used in the rest of the codebase as well and there's one less correspondence to keep in the head.