[Haskell-cafe] Coding conventions for Haskell?

Alexander Solla ajs at 2piix.com
Mon Sep 27 00:41:16 EDT 2010


  On 09/25/2010 02:24 AM, Petr Pudlak wrote:
> Hi,
>
> sometimes I have doubts how to structure my Haskell code - where to 
> break lines, how much to indent, how to name functions and variables 
> etc. Are there any suggested/recommended coding conventions? I 
> searched a bit and I found a few articles and discussions:
>
I used a modified version of the "best practices" described by the Perl 
people for Perl code.  "Like things go under like things" is the most 
important rule to follow.  This rule, in other words, is a convention to 
make your code as "tabular" as possible.  Also, most expressions have an 
"outermost" connective.  I tend to align them:

Consider:

data Foo a b = Foo    a
              | Bar      b
              | Foobar a b

That's not so nice looking now, but consider what happens when you have 
four or five arguments:

type Label = String
type Address = String

data Foo a b = Foo      (Maybe Label)  Address a
              | Bar             Label             b
              | Foobar          Label   Address a b

This is rather neat.  Instead of focusing effort on parsing the source, 
we can merely compare lines for the differences in logic they embody.  
Compare it with an "un-normalized" definition:

data Foo a b = Foo (Maybe Label) Address a
              | Bar Label b
              | Foobar Label Address a b

Quick, which one of those has a b in it?  Moreover, it make 
editing/refactoring easier with tools like Vim (with its visual block 
mode) and TextMate.  I'm sure Emacs, etc have block editing modes too.

To that end, I try to keep in the style of this style.  For let-in 
pairs, I do:

expression a = let exp  = blah_blah  a
                    exp' = blah_blah' a
                 in (exp ++ exp')

I usually keep parentheses aligned as well, if a pair won't fit in a 
line.  That's one of the more obvious consequences of my convention.  
Monadic operators are worth keeping together, for similar reasons as 
keeping parentheses aligned.

action = first >>= second >>= third -- :fits on one line

-- Steps added:
action = first
 >>= second
 >>= third
 >>= fourth
 >>= fifth

You can jump into do notation pretty easily from there, by deleting the 
 >>= operators, and sticking a 'do' before first.

Remember to treat values, functions, and monadic actions as "servers" 
that respond to your requests.  This is the easiest way to maximize the 
value of Haskell's laziness.

Also, and finally, remember that a function is a special kind of join on 
data types.  (A many-to-one join, in terms of the relational algebra as 
spoken of by database people).  My approach makes it easy to "abstract 
operators out" of the act of reading.


More information about the Haskell-Cafe mailing list