Anticapitalist Casing with HLint

I would like to implement a new hlint rule that emits the following advice for left hand sides of definitions: (examples drawn from the warp-tls package)

runTLS ×
runTLSSocket ×
TLSSettings  ×
defaultTlsSettings √
tlsSettings √
tlsSettingsChain √
tlsSettingsMemory √
tlsSettingsChainMemory √
tlsSettingsRef √
tlsSettingsChainRef √
CertSettings √
tlsCredentials √
tlsServerHooks √
tlsServerDHEParams ×
WarpTLSException ×

I.e., I want to warn about identifiers that contain consecutive capitals.

Note that we can not generally make identifiers conformant automatically: SMSOTPToken should be SmsOtpToken, but there is no way to determine where one capitalism ends and another begins.

Is this a good idea and would anyone be interested in using this?

(Full disclosure: This is the style we want to enforce at work)


I did not find a comprehensive list of hlint suggestions, but I think hlint does the job of spotting code redundancies/suggesting simplifications.

I think what you propose is quite sensible, but more suitable to a code formatter like fourmolu/ormolu rather than hlint.

Hlint actually already has a similar rule for turning snake case into camel case:


This is pertinent to me in that I agree that run-on capitals are garbage, but also I have a use case where it doesn’t work so well. Lately I’ve been faced with the question of: “What do you do when you are referencing something that is canonically specified as uppercase?” Similarly, "What do you do when you have sequences of numbers that must be separated?

In my case, cryptographic identifiers are almost exclusively acronyms mixed with numbers that get glommed together, and to refer to them in anything but the exact identifier is strongly dissuaded to avoid confusion. However, this might be the exception that proves the rule. I’m not sure anything can really be done to make things like cbc_gost_28147_89_pkcs7 more palatable. :upside_down_face:


I’d argue that this is not about formatting but the actual code, so hlint would be the right place for it.

1 Like

I can see the dilemma. We are all used to writing TLS, SMS and OTP in a sentence, so these are also “canonically uppercase”, except when your identifier style is camel case, this becomes hard to parse for the reader.

So maybe capitalisms should be allowed if the identifier contains underscores :man_shrugging:

The worst rule in hlint.

1 Like

Why is that the worst rule?

Because I like snake case and feel annoyed every time hlint suggests I use camel case instead. HLint telling me to simplify some expression by using a library function: good. Hlint telling me how to style my code: infuriating.

Why do you like snake case [1]

Well there are a few reasons:

  • It doesn’t actually run into the camelCase problem this thread is about. SMSOTPToken is hard to figure out where the separate words start and end. SMS_OTP_token is perfectly legible.
  • Even in non ambiguous situations, snake case mimics spaces. Spaces are how you’d separate words if you could, so it makes sense to me to mimic them.
  • My screen is wider than 80 characters and my editor lets me zoom out and scroll easily. I have no reason to be stingy in my character usage.

[1] I’m assuming this is your next question

Those are fine reasons to like snake case. Can’t you just turn that rule off? Then hlint will not bother you about it.

I’m concerned with improving an aspect of camelCase, which seems to be the preferred style in Haskell.

As a general rule, I don’t like snake_case, because of the fact that space is function application in Haskell, and having ambiguous spaces (the underscores) in snake case identifiers makes reading code harder/annoying.

When you have SMSOTPToken situations, though, SMS_OTP_Token would probably be something I’d use too and wouldn’t mind if it was defined as such in an external library.

If anything, it’d be nice if HLint had the possibility to more granularly ignore rules on certain lines or for certain identifiers or something.

1 Like