packages feed

hlint-1.2: hlint.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
        <title>HLint Manual</title>
        <style type="text/css">
pre {
    border: 2px solid gray;
    padding: 1px;
    padding-left: 5px;
    margin-left: 10px;
    background-color: #eee;
}

pre.define {
    background-color: #ffb;
    border-color: #cc0;
}

body {
    font-family: sans-serif;
}

h1, h2, h3 {
    font-family: serif;
}

h1 {
    color: rgb(23,54,93);
    border-bottom: 1px solid rgb(79,129,189);
    padding-bottom: 2px;
    font-variant: small-caps;
    text-align: center;
}

a {
    color: rgb(54,95,145);
}

h2 {
    color: rgb(54,95,145);
}

h3 {
    color: rgb(79,129,189);
}

p.rule {
    background-color: #ffb;
	padding: 3px;
	margin-left: 50px;
	margin-right: 50px;
}
        </style>
    </head>
    <body>

<h1>HLint Manual</h1>

<p style="text-align:right;margin-bottom:25px;">
    by <a href="http://www.cs.york.ac.uk/~ndm/">Neil Mitchell</a>
</p>

<p>
	<a href="http://www.cs.york.ac.uk/~ndm/hlint/">HLint</a> 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:
</p>
<ol>
    <li>Installing and running HLint</li>
    <li>Adding additional hints</li>
    <li>Ignoring particular hints</li>
</ol>

<h3>Acknowledgements</h3>

<p>
	This program has only been made possible by the presence of the <a href="http://www.cs.chalmers.se/~d00nibro/haskell-src-exts/">haskell-src-exts</a> package, and many useful improvements have been made by <a href="http://www.cs.chalmers.se/~d00nibro/">Niklas Broberg</a> in response to feature requests.
</p>

<h3>Bugs and limitations</h3>

<p>
	A complete bug list is kept at <a href="http://code.google.com/p/ndmitchell/issues/list?q=proj:HLint">my bug tracker</a>.
</p>

<h2>Installing and running HLint</h2>

<p>
	Installation follows the standard pattern of any Haskell library or program, simply type <tt>cabal update</tt> to update your local hackage database, then <tt>cabal install hlint</tt> to install HLint.
</p><p>
	Once HLint is installed, simply run <tt>hlint <i>source</i></tt> where <i>source</i> is either a Haskell file or a directory containing some Haskell files. Any directory will be searched recursively for any files ending with <tt>.hs</tt> or <tt>.lhs</tt>. For example, running HLint over darcs would give:
</p>
<pre>

$ hlint darcs-2.1.2

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

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

darcs-2.1.2\src\Darcs\Patch\Test.lhs:306:1: Error: 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 ...
</pre>
<p>
	Each suggestion says which file/line the suggestion relates to, how serious the issue is, 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 <tt>concat</tt> and <tt>map</tt> separately, it would be better to use the combination function <tt>concatMap</tt>.
</p><p>
	The first suggestion is marked as an error, because using <tt>concatMap</tt> in preference to the two separate functions is always desirable. In contrast, the removal of brackets is probably a good idea, but not always. Reasons that a hint might be a warning include requiring an additional import, something not everyone agrees on, and functions only available in more recent versions of the base library.
</p>
<p class="rule">
	<b>Disclaimer:</b> While these hints are meant to be correct, they aren't guaranteed to be. Please report any non equivalent hints (ignoring effects of <tt>seq</tt>).
</p>

<h3>Reports</h3>

<p>
	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 <tt>--report</tt> 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.
</p>

<h3>Recursive Suggestions</h3>

<p>
	Suggestions are not applied recursively. Consider:
</p>
<pre>
foo xs = concat (map op xs)
</pre>
<p>
	This will suggest eta reduction to <tt>concat . map op</tt>, and then after making that change and running HLint again, will suggest use of <tt>concatMap</tt>. Many people wonder why HLint doesn't directly suggest <tt>concatMap op</tt>. There are a number of reasons:
</p>
<ul>
	<li>HLint aims to both improve code, and to teach the author better style. Doing modifications individually helps this process.</li>
	<li>Sometimes the steps are reasonably complex, by automatically composing them the user may become confused.</li>
	<li>Sometimes HLint gets transformations wrong - particularly with operators. If suggestions are applied recursively, one error will cascade.</li>
	<li>Some people only make use of some of the suggestions. In the above example using concatMap is a good idea, but sometimes eta reduction isn't. By suggesting them separately, people can pick and choose.</li>
	<li>Sometimes a transformed expression will be large, and a further hint will apply to some small part of the result, which appears confusing.</li>
	<li>Consider <tt>f $ (a b)</tt>. There are two valid hints, either remove the <tt>$</tt> or remove the brackets, but only one can be applied.</li>
</ul>


<h2>Adding additional hints</h2>

<p>
	The majority of hints are contained in a <tt>Hints.hs</tt> 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. In addition, any <tt>Hints.hs</tt> in the current directory, or specified with the <tt>--hint</tt> flag, will be used. As an example of a hint file, the line specifying <tt>concatMap</tt> is:
</p>
<pre>
error = concat (map f x) ==> concatMap f x
</pre>
<p>
	The line can be read as replace <tt>concat (map <i>f</i> <i>x</i>)</tt> with <tt>concat (map <i>f</i> <i>x</i>)</tt>. Anything with a 1-letter variable is treated as a substitution parameter. For examples of more complex hints see the supplied hints file. In general, hints should <i>not</i> be given in point free style, as this reduces the power of the matching. Hints may start with <tt>error</tt> or <tt>warn</tt> to denote how severe they are by default.
</p><p>
	If you come up with interesting hints, please submit them. For example, some of the hints about <tt>last</tt> were supplied by Henning Thielemann.
</p>


<h2>Ignoring particular hints</h2>

<p>
	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 hint files. Some example directives are:
</p>
<ul>
	<li><tt>ignore "Eta reduce" = ""</tt> - supress all eta reduction suggestions.</li>
	<li><tt>ignore "Eta reduce" = Data.List Prelude</tt> - supress eta reduction hints in the Prelude and Data.List modules.</li>
	<li><tt>ignore = Data.List.map</tt> - don't give any hints in the function Data.List.map.</li>
	<li><tt>error = Data.List.map</tt> - any hint in the function is an error.</li>
	<li><tt>error "Use concatMap" = ""</tt> - the hint to use concatMap is an error.</li>
	<li><tt>warn "Use concatMap" = ""</tt> - the hint to use concatMap is a warning.</li>
</ul>
<p>
	These directives are applied in the order they are given, with later hints overriding earlier ones.
</p>

    </body>
</html>