[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