Rewriting to Haskell–Linting

Posted on April 20, 2020 by Riccardo

Rewriting to Haskell (Series)

Rewriting to Haskell–IntroRewriting to Haskell–Project SetupRewriting to Haskell–DeploymentRewriting to Haskell–Automatic FormattingRewriting to Haskell–ConfigurationRewriting to Haskell–Standing on the shoulders of RailsRewriting to Haskell–Making GHC More NitpickyRewriting to Haskell–TestingRewriting to Haskell–LintingRewriting to Haskell–Parsing Query ParamsRewriting to Haskell–Parsing Query Params, AgainRewriting to Haskell–Errors

I bet most of us are not surrounded by as many haskellers as we would wish. That means we need to treasure every ounce of feedback we can get. Turns out a linter is a great way of squeezing some more.

We recently added HLint to Stream. What follows are some of the changes we've made thanks to its suggestions.

Unused LANGUAGE pragma:

 {-# LANGUAGE DataKinds #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE TypeOperators #-}

Use infix:

-toChannels channel = intersect activeChannels [channel]
+toChannels channel = activeChannels `intersect` [channel]

Redundant bracket:

-  toField (Disabled) = toField ("NULL" :: Text)
+  toField Disabled = toField ("NULL" :: Text)

Redundant $:

-  toField NoQuery = toField $ ("%" :: Text)
+  toField NoQuery = toField ("%" :: Text)

Redundant do:

-findPosts connection searchQuery searchQuantity searchComments searchChannels searchLastId = do
+findPosts connection searchQuery searchQuantity searchComments searchChannels searchLastId =
   query connection (sqlQuery searchLastId) (searchQuery, searchQuery, searchComments, searchChannels, searchQuantity)

Eta reduce:

-  random g = randomR (minBound, maxBound) g
+  random = randomR (minBound, maxBound)
-server configuration connection = getSearchResults configuration connection
+server = getSearchResults

Use <$> (instead of >>= pure):

-  updatedAt <- randomUTCTime >>= pure . utcToLocalTime (read "UTC")
+  updatedAt <- utcToLocalTime (read "UTC") <$> randomUTCTime
-  createdAt <- maybe randomUTCTime pure mCreatedAt >>= pure . utcToLocalTime (read "UTC")
+  createdAt <- utcToLocalTime (read "UTC") <$> maybe randomUTCTime pure mCreatedAt

Hints provided by HLint should be taken as such. In our case, we took what felt right and left the rest out. This is why we do not run HLint in CI. However, there are many ways of integrating it to get the best out without the pain of broken builds. Be sure to take a look at the readme cause there's a lot of additional goodness (e.g. automatically applying hints).


It's one of the selected few I follow every week – Mateusz

Tired of RELEARNING webdev stuff?

  • A 100+ page book with the best links I curated over the years
  • An email once a week full of timeless software wisdom
  • Your recommended weekly dose of pink
  • Try before you buy? Check the archives.