Rewriting to Haskell–Making GHC More Nitpicky

Posted on April 6, 2020 by Riccardo
Functional ProgrammingHaskellServant

This is part of a series:

GHC by default compiles with some warnings enabled. But there’s a ton more. Thus, we decided to turn on several. Also, we have the compiler treat them as errors with -Wall. Luckily, Max Tagher did all the work for us and prepared a “Copy-Pastable List” with nice explanations for us lazy developers. Thanks Max!

This is what we threw in package.yaml:

   source-dirs: src
+  ghc-options:
+    # For details on warnings:
+    # This list taken from
+    # Enable all warnings with -Weverything, then disable the ones we don’t care about
+    - -Weverything
+    - -Werror
+    - -Wno-missing-exported-signatures # missing-exported-signatures turns off the more strict -Wmissing-signatures. See
+    - -Wno-missing-import-lists # Requires explicit imports of _every_ function (e.g. ‘$’); too strict
+    - -Wno-missed-specialisations # When GHC can’t specialize a polymorphic function. No big deal and requires fixing underlying libraries to solve.
+    - -Wno-all-missed-specialisations # See missed-specialisations
+    - -Wno-unsafe # Don’t use Safe Haskell warnings
+    - -Wno-safe # Don’t use Safe Haskell warnings
+    - -Wno-missing-local-signatures # Warning for polymorphic local bindings; nothing wrong with those.
+    - -Wno-monomorphism-restriction # Don’t warn if the monomorphism restriction is used

Turns out we have been disciplined enough to just need a few edits to fix the new errors. What follows is a non-comprehensive list of the changes we performed together with the warning that was triggered.


-module Api.Search where
+module Api.Search
+  ( SearchAPI,
+    getResults,
+  )


 import Servant ((:>), Get, Handler, JSON, QueryParam)
+import Prelude


 instance FromJSON Configuration where
   parseJSON (Object x) = do
     -- ...
+  parseJSON _ = fail "was expecting an object"


+joinComments :: Query
 joinComments = "LEFT JOIN comments ON = comments.post_id"

+textOrTitle :: Query
 textOrTitle = "(posts.text ILIKE ? OR posts.title ILIKE ?)"

Some warnings can be annoying or even unneeded depending on the use-case, your mileage may vary. Feel free to treat this as a starting point and tweak the options down the line.

Support my work by tweeting this article! 🙏