HLint Manual

by Neil Mitchell

HLint is a tool for suggesting possible improvements to Haskell code. These suggestions include ideas such as using alternative functions, simplifying code and spotting redundancies. This document is structured as follows:

  1. Installing and running HLint
  2. Adding additional hints
  3. Ignoring certain hints

Acknowledgements

This program has only been made possible by the presence of the haskell-src-exts package, and many useful improvements have been made by Niklas Broberg in response to feature requests.

Bugs and limitations

Installing and running HLint

Installation follows the standard pattern of any Haskell library or program, simply type cabal update to update your local hackage database, then cabal install hlint to install HLint.

Once HLint is installed, simply run hlint source where source is either a Haskell file or a directory containing some Haskell files. For example, running HLint over darcs would give:


$ hlint darcs-2.1.2

darcs-2.1.2\src\CommandLine.lhs:94:1: Use concatMap
Found:
  concat $ map escapeC s
Why not:
  concatMap escapeC s

darcs-2.1.2\src\CommandLine.lhs:103:1: Use fewer brackets
Found:
  ftable ++ (map (\ (c, x) -> (toUpper c, urlEncode x)) ftable)
Why not:
  ftable ++ map (\ (c, x) -> (toUpper c, urlEncode x)) ftable

darcs-2.1.2\src\Darcs\Patch\Test.lhs:306:1: Use a more efficient monadic variant
Found:
  mapM (delete_line (fn2fp f) line) old
Why not:
  mapM_ (delete_line (fn2fp f) line) old

... lots more suggestions ...

Each suggestion says which file/line the suggestion relates to, a description of the issue, what it found, and what you might want to replace it with. In the case of the first hint, it has suggested that instead of applying concat and map separately, it would be better to use the combination function concatMap.

Disclaimer: While these hints are meant to be correct, they aren't guaranteed to be. Please report non equivalent code which doesn't involve incorrect parsing of infix operators (see Bugs above), and is incorrect without seq.

Reports

HLint can generate a lot of information, and often searching for either the errors specific to a file, or a specific class of errors, is difficult. Using the --report flag HLint will produce a report file in HTML, which can be viewed interactively. It is recommended that if investigating more than a handlful of hints, a report is used.

Adding additional hints

The majority of hints are contained in a Hints.hs file which will be installed in the appropriate data directory by Cabal. This file may be freely edited, to add library specific knowledge, or to include hints that may have been missed. As an example of the contents of this file, the line specifying concatMap is:

hint = concat (map f x) ==> concatMap f x

The line can be read as replace concat (map f x) with concat (map f x). Anything with a 1-letter variable is treated as a substitution parameter. For examples of more complex hints see the supplied hints file.

If you come up with interesting hints, please submit them. For example, some of the hints about last were supplied by Henning Thielemann.

Ignoring certain hints

Some of the hints are subjective, and some users believe they should be ignored. Some hints are applicable usually, but occasionally don't always make sense. The ignoring mechanism provides features for supressing certain hints. Ignore directives are picked up from the hlint_ignore.txt file from the users data directory, along with any files specified with -I and any directives specified with -i. Some example directives are:

In hint files, any lines which are blank or start with the # character are ignored.