Programming-Guidelines.txt revision f09bc2a9244ed29b02ec8dd58a3040f8acb467ba
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasProgramming guidelines shall help to make the code of a project better
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasreadable and maintainable by the varying number of contributors.
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasIt takes some programming experience to develop something like a
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiaspersonal "coding style" and guidelines only serve as rough shape for
fc09e0a6af734edbd944dd8082bb51985c233b43Alexis Tsogiascode. Guidelines should be followed by all members working on the
fc09e0a6af734edbd944dd8082bb51985c233b43Alexis Tsogiasproject even if they prefer (or are already used to) different
fc09e0a6af734edbd944dd8082bb51985c233b43Alexis Tsogiasguidelines.
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis TsogiasIn the following I will describe documentation, file format, naming
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasconventions and good programming practice (adapted form Matt's C/C++
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasProgramming Guidelines and the Linux kernel coding style).
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias---------------------------------------------------------------------------
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasDocumentation:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasComments are to be written in application terms (i.e. user's point of
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasview). Don't use technical terms - that's what the code is for!
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasComments should be written using correct spelling and grammar in complete
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiassentences with punctation (in English only).
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias"Generally, you want your comments to tell WHAT your code does, not HOW.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasAlso, try to avoid putting comments inside a function body: if the
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasfunction is so complex that you need to separately comment parts of it,
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasyou should probably" (... decompose it)
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasPut a haddock comment on top of every exported function and data type!
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasMake sure haddock accepts these comments.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasFile Format:
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasAll Haskell source files start with a haddock header of the form:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias{- |
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasModule : <File name, i.e. generated by \$Header\$>
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasDescription : <Short text displayed on contents page>
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasCopyright : (c) <You> and <Your affiliation>
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasLicense : similar to LGPL, see LICENSE.txt
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
748e10233de9e76b68be4f0050c7b4a7f3c415eaAlexis TsogiasMaintainer : maeder@tzi.de
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasStability : provisional
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasPortability : portable
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias<module description starting at first column>
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias-}
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasA possible compiler pragma (like {-# OPTIONS -cpp #-}) may precede
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogiasthis header. The following hierarchical module name must of course
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasmatch the file name.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasMake sure that the description is changed to meet the module (if the
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogiasheader was copied from elsewhere). Insert your email address as maintainer.
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasTry to write portable (Haskell98) code. If you (indirectly) import
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogiasa module that uses i.e. multi-parameter type classes and functional
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasdependencies the code becomes "non-portable (MPTC with FD)".
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasThe Dollar-Header-Dollar entry is automatically expanded by cvs (and will wrap
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogiasaround). All other lines should not be longer than 80 (preferably 75)
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis Tsogiascharacters to avoid wrapped lines (for casual readers)!
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
e21e5f0fa66bf80e14cfd3f571e09b3952e46ad9Alexis TsogiasExpand all your tabs to spaces to avoid the danger of wrongly expanding
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasthem (or a different display of tabs versus eight spaces). Possibly put
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiassomething like the following in your ~/.emacs file.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias (custom-set-variables '(indent-tabs-mode nil))
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasThe last character in your file should be a newline! Under solaris
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasyou'll get a warning if this is not the case and sometimes last lines
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiaswithout newlines are ignored (i.e. "#endif" without newline). Emacs
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasusually asks for a final newline.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasThe whole module should not be too long (about 400 lines)
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasNaming Conventions:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasIn Haskell types start with capital and functions with lowercase
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasletters, so only avoid infix identifiers! Defining symbolic infix
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasidentifiers should be left to library writers only.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias(The infix identifier "\\" at the end of a line causes cpp preprocessor
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasproblems.)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasNames (especially global ones) should be descriptive and if you need
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiaslong names write them as mixed case words (aka camelCase). (but "tmp"
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasis to be preferred over "thisVariableIsATemporaryCounter")
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasGood Programming Practice:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias"Functions should be short and sweet, and do just one thing. They should
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasfit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasas we all know), and do one thing and do that well."
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasMost haskell functions should be at most a few lines, only case
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasexpression over large data types (that should be avoided, too) may need
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiascorresponding space.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasThe code should be succinct (though not obfuscated), readable and easy to
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasmaintain (after unforeseeable changes). Don't exploit exotic language
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasfeatures without good reason.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasIt's not fixed how deep you indent (4 or 8 chars). You can break the
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasline after "do", "let", "where", and "case .. of". Make sure that
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasrenamings don't destroy your layout. (If you get to far to the right,
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogiasthe code is unreadable anyway and needs to be decomposed.)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasBad:
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias case foo of Foo -> "Foo"
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias Bar -> "Bar"
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasGood:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias case <longer expression> of
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias Foo -> "Foo"
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias Bar -> "Bar"
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasAvoid the notation with braces and semicolons since the layout rule
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasforces you to properly align your alternatives.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasRespect compiler warnings. Supply type signatures, avoid shadowing and
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasunused variables. Particularly avoid non-exhaustive and
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasoverlapping patterns. Missing unreachable cases can be filled in using
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias"error" with a fixed string "<ModuleName>.<function>" to indicate the
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogiaserror position (in case the impossible should happen). Don't invest
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiastime to "show" the offending value, only do this temporarily when
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasdebugging the code.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasDon't leave unused or commented-out code in your files! Readers don't
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasknow what to think of it.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasCase expressions
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasPrefer case expressions over pattern binding declarations.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasNot always nice:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias longFunctionName (Foo: _ : _) = e1
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias longFunctionName (Bar: _) = e2
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasBetter (I think):
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias longFunctionName arg = case arg of
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias Foo : _ : _ -> e1
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias Bar : _ -> e2
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias _ -> error "ProgrammingGuidelines.longFunctionName"
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasFor partial functions document their preconditions (if not obvious)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasand make sure that partial functions are only called when
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiaspreconditions are obviously fulfilled (i.e. by a case statement or a
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasprevious test). Particularly the call of "head" should be used with
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiascare or (even better) be made obsolete by a case statement.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasUsually a case statement (and the import of isJust and fromJust from
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasData.Maybe) can be avoided by using the "maybe" function:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias maybe (error "<ModuleName>.<function>") id $ Map.lookup key map
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasGenerally we require you to be more explicit about failure
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiascases. Surely a missing (or an irrefutable) pattern
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiaswould precisely report the position of a runtime error, but these are
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasnot so obvious when reading the code.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasDo avoid mixing "let" and "where". (I prefer "let" and have auxiliary
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasfunction on the top-level that are not exported.) Export lists also
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiassupport the detection of unused functions.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasIf you notice that you're doing the same task again, try to generalize
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasit in order to avoid duplicate code. It is frustrating to change the
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiassame error in several places.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasApplication notation
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasMany parentheses can be eliminated using the infix application operator "$"
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiaswith lowest priority. Try at least to avoid unnecessary parentheses in
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasstandard infix expression.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias f x : g x ++ h x
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias a == 1 && b == 1 || a == 0 && b == 0
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasRather than putting a large final argument in parentheses (with a
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasdistant closing one) consider using "$" instead.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias"f (g x)" becomes "f $ g x" and consecutive applications
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias"f (g (h x))" can be written as "f $ g $ h x" or "f . g $ h x".
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasA function definition like
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias"f x = g $ h x" can be abbreviated to "f = g . h".
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasNote that the final argument may even be an infix- or case expression:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias map id $ c : l
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias filter (const True) . map id $ case l of ...
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasHowever, be aware that $-terms cannot be composed further in infix
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasexpressions.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasProbably wrong:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias f $ x ++ g $ x
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasBut the scope of an expression is also limited by the layout rule, so
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasit is usually save to use "$" on right hand sides.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasOk:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias do y <- f $ l
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias ++
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias do y <- g $ l
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasOf course "$" can not be used in types. GHC has also some primitive
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasfunctions involving the kind "#" that cannot be applied using "$".
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasLast warning: always leave spaces around "$" (and other mixfix
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasoperators) since a clash with template haskell is possible.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias(Also write "\ t" instead of "\t" in lambda expressions)
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis TsogiasList Comprehensions
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias---------------------------------------------------------------------------
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis TsogiasUse these only when "short and sweet". Prefer map, filter, and foldr!
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis TsogiasInstead of:
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias [toUpper c | c <- s]
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiaswrite:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias map toUpper s
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasConsider:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias [toUpper c | s <- strings, c <- s]
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasHere it takes some time for the reader to find out which value depends
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiason what other value and it is not so clear how many times the interim
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasvalues s and c are used. In contrast to that the following can't be clearer:
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias map toUpper (concat strings)
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasWhen using higher order functions you can switch easier to data
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasstructures different from list. Compare:
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias map (1+) list
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasand:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias Set.map (1+) set
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasTypes
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasPrefer proper data types over type synonyms or tuples even if you have
4e95ffc23b9c5f0b5980ab6f1cacbe7bd9789851Alexis Tsogiasto do more constructing and unpacking. This will make it easier to
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiassupply class instances later on. Don't put class constraints on
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasa data type, constraints belong only to the functions that manipulate
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasthe data.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasUsing type synonyms consistently is difficult over a longer time,
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasbecause this is not checked by the compiler. (The types shown by
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasthe compiler may be unpredictable: i.e. FilePath, String or [Char])
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasTake care if your data type has many variants (unless it is an
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasenumeration type.) Don't repeat common parts in every variant since
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasthis will cause code duplication.
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasBad (to handle arguments in sync):
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias data Mode f p = Box f p | Diamond f p
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasGood (to handle arguments only once):
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias data BoxOrDiamond = Box | Diamond
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias data Mode f p = Mode BoxOrDiamond f p
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasConsider (bad):
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias data Tupel a b = Tupel a b | Undefined
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasversus (better):
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias data Tupel a b = Tupel a b
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasand using:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias Maybe (Tupel a b)
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias(or another monad) whenever an undefined result needs to be propagated
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasRecords
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasFor (large) records avoid the use of the constructor directly and
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasremember that the order and number of fields may change.
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasTake care with (the rare case of) depend polymorphic fields:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias data Fields a = VariantWithTwo
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias { field1 :: a
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias , field2 :: a }
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasThe type of a value v can not be changed by only setting field1:
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias v { field1 = f }
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasBetter construct a new value:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias VariantWithTwo { field1 = f } -- leaving field2 undefined
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasOr use a polymorphic element that is instantiated by updating:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias empty = VariantWithTwo { field1 = [], field2 = [] }
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias empty { field1 = [f] }
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasSeveral variants with identical fields may avoid some code duplication
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiaswhen selecting and updating, though possibly not in a few
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasdepended polymorphic cases.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasHowever, I doubt if the following is a really good alternative to the
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasabove data Mode with data BoxOrDiamond.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias data Mode f p =
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias Box { formula :: f, positions :: p }
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias | Diamond { formula :: f, positions :: p }
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasIO
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias---------------------------------------------------------------------------
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasTry to strictly separate IO, Monad and pure (without do) function
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasprogramming (possibly via separate modules).
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasBad:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias x <- return y
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias ...
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasGood:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias let x = y
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias ...
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasDon't use Prelude.interact and make sure your program does not depend
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiason the (not always obvious) order of evaluation. I.e. don't read and
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiaswrite to the same file:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasThis will fail:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias do s <- readFile f
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias writeFile f $ 'a' : s
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasbecause of lazy IO! (Writing is starting before reading is finished.)
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasTrace
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasTracing is for debugging purposes only and should not be used as
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasfeedback for the user. Clean code is not cluttered by trace calls.
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasImports
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasStandard library modules like Char. List, Maybe, Monad, etc should be
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasimported by their hierarchical module name, i.e. the base package (so
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogiasthat haddock finds them):
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias import Data.List
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias import Control.Monad
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias import System.Environment
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis TsogiasThe libraries for Set and Map are to be imported qualified:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias import qualified Data.Set as Set
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias import qualified Data.Map as Map
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasGlasgow extensions and Classes
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasStay away form extensions as long as possible. Also use classes with
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiascare because soon the desire for overlapping instances (like for lists
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasand strings) may arise. Then you may want MPTC (multi-parameter type
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasclasses), functional dependencies (FD), undecidable and possibly incoherent
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasinstances and then you are "in the wild" (according to SPJ).
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasFinal remarks:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias---------------------------------------------------------------------------
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasDespite guidelines, writing "correct code" (without formal proof
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiassupport yet) still remains the major challenge. As motivation to
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogiasfollow these guidelines consider the points that are from the "C++
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasCoding Standard", where I replaced "C++" with "Haskell".
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasGood Points:
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * programmers can go into any code and figure out what's going on
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * new people can get up to speed quickly
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * people new to Haskell are spared the need to develop a personal
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias style and defend it to the death
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * people new to Haskell are spared making the same mistakes over
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias and over again
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * people make fewer mistakes in consistent environments
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * programmers have a common enemy :-)
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasBad Points:
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * the standard is usually stupid because it was made by someone
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias who doesn't understand Haskell
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * the standard is usually stupid because it's not what I do
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * standards reduce creativity
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * standards are unnecessary as long as people are consistent
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias * standards enforce too much structure
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias * people ignore standards anyway
12f6880fc0909e8dc2bdebc5f299a6a8bfa8afa7Alexis Tsogias
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis TsogiasSend comments to the "Maintainer" of this file
409eb8adf8c7ee0609aef256b67f5dfad2fb6386Alexis Tsogias